From f6043d76f861c272cd59f1f14b010fa85095caad Mon Sep 17 00:00:00 2001 From: Song Guo Date: Mon, 12 Apr 2021 15:12:20 +0800 Subject: [PATCH 01/17] [controller] Use interaction model for commands --- src/app/chip_data_model.gni | 6 +----- src/app/server/Server.cpp | 2 -- .../templates/app/CHIPClusters-src.zapt | 6 ------ src/controller/CHIPDevice.cpp | 2 -- src/controller/CHIPDevice.h | 2 -- src/controller/CHIPDeviceController.cpp | 2 -- src/controller/CHIPDeviceController.h | 2 -- .../python/ChipDeviceController-ScriptBinding.cpp | 12 ++++-------- src/lib/core/BUILD.gn | 1 - src/lib/core/core.gni | 3 --- 10 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index ce1bc7b6c28ffa..2ad90d84082170 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -108,6 +108,7 @@ template("chip_data_model") { "${_app_root}/util/process-cluster-message.cpp", "${_app_root}/util/process-global-message.cpp", "${_app_root}/util/util.cpp", + "${invoker.zap_pregenerated_dir}/IMClusterCommandHandler.cpp", ] if (defined(invoker.cluster_sources)) { @@ -152,11 +153,6 @@ template("chip_data_model") { if (_use_default_client_callbacks) { sources += [ "${invoker.zap_pregenerated_dir}/CHIPClientCallbacks.cpp" ] } - - if (chip_enable_interaction_model) { - sources += - [ "${invoker.zap_pregenerated_dir}/IMClusterCommandHandler.cpp" ] - } } if (!defined(public_deps)) { diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 0b5548d4a16aa6..20532df6467c61 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -513,10 +513,8 @@ void InitServer(AppDelegate * delegate) err = gExchangeMgr.Init(&gSessions); SuccessOrExit(err); -#if CHIP_ENABLE_INTERACTION_MODEL err = chip::app::InteractionModelEngine::GetInstance()->Init(&gExchangeMgr, nullptr); SuccessOrExit(err); -#endif #if defined(CHIP_APP_USE_ECHO) err = InitEchoHandler(&gExchangeMgr); diff --git a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt index 52a06547e13163..ce7eb4ca622821 100644 --- a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt @@ -19,7 +19,6 @@ namespace Controller { {{#chip_server_cluster_commands}} CHIP_ERROR {{asCamelCased clusterName false}}Cluster::{{asCamelCased name false}}(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -44,11 +43,6 @@ CHIP_ERROR {{asCamelCased clusterName false}}Cluster::{{asCamelCased name false} ReturnErrorOnFailure(ZCLcommand->FinishCommand()); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encode{{asCamelCased clusterName false}}Cluster{{asType name}}Command(seqNum, mEndpoint{{#chip_server_cluster_command_arguments}}, {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } {{/chip_server_cluster_commands}} diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index f0c22e912fc7a5..506ba229a98685 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -411,10 +411,8 @@ void Device::InitCommandSender() mCommandSender->Shutdown(); mCommandSender = nullptr; } -#if CHIP_ENABLE_INTERACTION_MODEL CHIP_ERROR err = chip::app::InteractionModelEngine::GetInstance()->NewCommandSender(&mCommandSender); ChipLogFunctError(err); -#endif } } // namespace Controller diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 195c5c13217932..c7141cc06500e9 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -176,9 +176,7 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate mBleLayer = params.bleLayer; #endif -#if CHIP_ENABLE_INTERACTION_MODEL InitCommandSender(); -#endif } /** diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index eba683842cac25..0a318158149353 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -179,10 +179,8 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, ControllerInitParams par err = mExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::TempZCL::Id, this); SuccessOrExit(err); -#if CHIP_ENABLE_INTERACTION_MODEL err = chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, params.imDelegate); SuccessOrExit(err); -#endif mExchangeMgr->SetDelegate(this); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 055dd8168d4a7e..46da5e9a300ec6 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -72,9 +72,7 @@ struct ControllerInitParams #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * bleLayer = nullptr; #endif -#if CHIP_ENABLE_INTERACTION_MODEL app::InteractionModelDelegate * imDelegate = nullptr; -#endif #if CHIP_DEVICE_CONFIG_ENABLE_MDNS DeviceAddressUpdateDelegate * mDeviceAddressUpdateDelegate = nullptr; #endif diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index b02820792fe200..c4c597e4ebab4f 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -136,15 +136,11 @@ CHIP_ERROR pychip_DeviceController_NewDeviceController(chip::Controller::DeviceC ReturnErrorOnFailure(sOperationalCredentialsIssuer.Initialize()); - initParams.storageDelegate = &sStorageDelegate; - initParams.mDeviceAddressUpdateDelegate = &sDeviceAddressUpdateDelegate; - initParams.pairingDelegate = &sPairingDelegate; - + initParams.storageDelegate = &sStorageDelegate; + initParams.mDeviceAddressUpdateDelegate = &sDeviceAddressUpdateDelegate; + initParams.pairingDelegate = &sPairingDelegate; initParams.operationalCredentialsDelegate = &sOperationalCredentialsIssuer; - -#if CHIP_ENABLE_INTERACTION_MODEL - initParams.imDelegate = &PythonInteractionModelDelegate::Instance(); -#endif + initParams.imDelegate = &PythonInteractionModelDelegate::Instance(); SuccessOrExit(err = (*outDevCtrl)->Init(localDeviceId, initParams)); SuccessOrExit(err = (*outDevCtrl)->ServiceEvents()); diff --git a/src/lib/core/BUILD.gn b/src/lib/core/BUILD.gn index 63ceb6d754bd61..e60a34ddff2752 100644 --- a/src/lib/core/BUILD.gn +++ b/src/lib/core/BUILD.gn @@ -56,7 +56,6 @@ buildconfig_header("chip_buildconfig") { "CHIP_CONFIG_MEMORY_DEBUG_CHECKS=${chip_config_memory_debug_checks}", "CHIP_CONFIG_MEMORY_DEBUG_DMALLOC=${chip_config_memory_debug_dmalloc}", "CHIP_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES=false", - "CHIP_ENABLE_INTERACTION_MODEL=${chip_enable_interaction_model}", ] } diff --git a/src/lib/core/core.gni b/src/lib/core/core.gni index 5b4b7951806aff..15d6ea268c3757 100644 --- a/src/lib/core/core.gni +++ b/src/lib/core/core.gni @@ -44,9 +44,6 @@ declare_args() { # Memory management debug option: use dmalloc chip_config_memory_debug_dmalloc = false - - # Overall experimental options for CHIP - chip_enable_interaction_model = false } if (chip_target_style == "") { From a8871caddac1d398f430088abca2775ac2cceb53 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Mon, 12 Apr 2021 17:02:11 +0800 Subject: [PATCH 02/17] Remove DispatchSingleClusterCommand default define --- examples/chip-tool/commands/clusters/ModelCommand.cpp | 11 +++++++++++ src/app/InteractionModelEngine.cpp | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/chip-tool/commands/clusters/ModelCommand.cpp b/examples/chip-tool/commands/clusters/ModelCommand.cpp index efe866b451800e..6b21d9ece1ba27 100644 --- a/examples/chip-tool/commands/clusters/ModelCommand.cpp +++ b/examples/chip-tool/commands/clusters/ModelCommand.cpp @@ -18,6 +18,7 @@ #include "ModelCommand.h" +#include #include using namespace ::chip; @@ -26,6 +27,16 @@ namespace { constexpr uint16_t kWaitDurationInSeconds = 10; } // namespace +void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId, + chip::TLV::TLVReader & aReader, Command * apCommandObj) +{ + ChipLogDetail(Controller, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId, + aCommandId, aEndPointId); + ChipLogError( + Controller, + "Default DispatchSingleClusterCommand is called, this should be replaced by actual dispatched for cluster commands"); +} + CHIP_ERROR ModelCommand::Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) { CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index b43e645a92cde9..4aa7e0f61ed068 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -243,17 +243,6 @@ void InteractionModelEngine::OnResponseTimeout(Messaging::ExchangeContext * ec) // The default implementation to make compiler happy before codegen for this is ready. // TODO: Remove this after codegen is ready. -void __attribute__((weak)) -DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId, - chip::TLV::TLVReader & aReader, Command * apCommandObj) -{ - ChipLogDetail(DataManagement, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId, - aCommandId, aEndPointId); - ChipLogError( - DataManagement, - "Default DispatchSingleClusterCommand is called, this should be replaced by actual dispatched for cluster commands"); -} - CHIP_ERROR __attribute__((weak)) ReadSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVWriter & aWriter) { ChipLogDetail( From 4fd061fcdb03763ab14b7b96a32c6cf51898d3d7 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Tue, 13 Apr 2021 09:53:15 +0800 Subject: [PATCH 03/17] Disable ember cluster message dispatch routine --- examples/lighting-app/nrfconnect/CMakeLists.txt | 2 ++ examples/lock-app/nrfconnect/CMakeLists.txt | 2 ++ src/app/util/process-cluster-message.cpp | 12 ++---------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index e49a94a7af7a39..5edd06d3e13d04 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -51,6 +51,7 @@ target_sources(app PRIVATE ${LIGHTING_COMMON}/gen/attribute-size.cpp ${LIGHTING_COMMON}/gen/call-command-handler.cpp ${LIGHTING_COMMON}/gen/callback-stub.cpp + ${LIGHTING_COMMON}/gen/IMClusterCommandHandler.cpp ${NRFCONNECT_COMMON}/util/LEDWidget.cpp ${NRFCONNECT_COMMON}/util/ThreadUtil.cpp ${NRFCONNECT_COMMON}/app/Service.cpp @@ -65,6 +66,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/binding-table.cpp ${CHIP_ROOT}/src/app/util/chip-message-send.cpp ${CHIP_ROOT}/src/app/util/client-api.cpp + ${CHIP_ROOT}/src/app/util/ember-compatibility-functions.cpp ${CHIP_ROOT}/src/app/util/ember-print.cpp ${CHIP_ROOT}/src/app/util/message.cpp ${CHIP_ROOT}/src/app/util/process-cluster-message.cpp diff --git a/examples/lock-app/nrfconnect/CMakeLists.txt b/examples/lock-app/nrfconnect/CMakeLists.txt index 4676e113043e1e..2338673f84cec1 100644 --- a/examples/lock-app/nrfconnect/CMakeLists.txt +++ b/examples/lock-app/nrfconnect/CMakeLists.txt @@ -51,6 +51,7 @@ target_sources(app PRIVATE ${LOCK_COMMON}/gen/attribute-size.cpp ${LOCK_COMMON}/gen/call-command-handler.cpp ${LOCK_COMMON}/gen/callback-stub.cpp + ${LOCK_COMMON}/gen/IMClusterCommandHandler.cpp ${NRFCONNECT_COMMON}/util/LEDWidget.cpp ${NRFCONNECT_COMMON}/util/ThreadUtil.cpp ${NRFCONNECT_COMMON}/app/Service.cpp @@ -65,6 +66,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/binding-table.cpp ${CHIP_ROOT}/src/app/util/chip-message-send.cpp ${CHIP_ROOT}/src/app/util/client-api.cpp + ${CHIP_ROOT}/src/app/util/ember-compatibility-functions.cpp ${CHIP_ROOT}/src/app/util/ember-print.cpp ${CHIP_ROOT}/src/app/util/message.cpp ${CHIP_ROOT}/src/app/util/process-cluster-message.cpp diff --git a/src/app/util/process-cluster-message.cpp b/src/app/util/process-cluster-message.cpp index 9e7549a129d81e..bf64d785b4a40b 100644 --- a/src/app/util/process-cluster-message.cpp +++ b/src/app/util/process-cluster-message.cpp @@ -56,8 +56,6 @@ bool emAfProcessClusterSpecificCommand(EmberAfClusterCommand * cmd) { - EmberAfStatus status; - // if we are disabled then we can only respond to read or write commands // or identify cluster (see device enabled attr of basic cluster) if (!emberAfIsDeviceEnabled(cmd->apsFrame->destinationEndpoint) && cmd->apsFrame->clusterId != ZCL_IDENTIFY_CLUSTER_ID) @@ -98,12 +96,6 @@ bool emAfProcessClusterSpecificCommand(EmberAfClusterCommand * cmd) } #endif - // Pass the command to the generated command parser for processing - status = emberAfClusterSpecificCommandParse(cmd); - if (status != EMBER_ZCL_STATUS_SUCCESS) - { - emberAfSendDefaultResponse(cmd, status); - } - - return true; + // All cluster messages (commands) will go through the IM now, return false to indicate an error. + return false; } From 9cc1737b4c8fd5d03c760b6f3dcaed5b0e9d665a Mon Sep 17 00:00:00 2001 From: Song Guo Date: Wed, 14 Apr 2021 15:50:48 +0800 Subject: [PATCH 04/17] Extract common code of deserialize procedure --- src/app/tests/TestCommandInteraction.cpp | 11 ++++ .../im_command_handler_cluster_commands.zapt | 64 +++++++++---------- .../app/im-cluster-command-handler.zapt | 18 +++++- src/controller/java/AndroidCommandHandler.cpp | 38 +++++++++++ src/controller/java/BUILD.gn | 1 + 5 files changed, 97 insertions(+), 35 deletions(-) create mode 100644 src/controller/java/AndroidCommandHandler.cpp diff --git a/src/app/tests/TestCommandInteraction.cpp b/src/app/tests/TestCommandInteraction.cpp index b96cbfd1f2f06e..400c42f35b6f08 100644 --- a/src/app/tests/TestCommandInteraction.cpp +++ b/src/app/tests/TestCommandInteraction.cpp @@ -22,6 +22,8 @@ * */ +#include + #include #include #include @@ -34,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +52,14 @@ static TransportMgr gTransportManager; static Transport::AdminId gAdminId = 0; namespace app { + +void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId, + chip::TLV::TLVReader & aReader, Command * apCommandObj) +{ + ChipLogDetail(Controller, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId, + aCommandId, aEndPointId); +} + class TestCommandInteraction { public: diff --git a/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt b/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt index 8ffd099caeeba1..c67df9f1a6c09f 100644 --- a/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt +++ b/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt @@ -1,9 +1,5 @@ {{#if (zcl_command_arguments_count this.id)}} -// 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. -CHIP_ERROR TLVError = CHIP_NO_ERROR; -CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; +expectArgumentCount = {{ zcl_command_arguments_count this.id }}; {{#zcl_command_arguments}} {{#if (isOctetString type)}} chip::ByteSpan {{asSymbol label}}; @@ -12,22 +8,38 @@ const uint8_t * {{asSymbol label}}; {{else}} {{asUnderlyingZclType type}} {{asSymbol label}}; {{/if}} -bool {{asSymbol label}}Exists = false; {{/zcl_command_arguments}} -uint32_t validArgumentCount = 0; +bool argExists[{{zcl_command_arguments_count this.id}}]; + +memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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 < {{zcl_command_arguments_count this.id}}) + { + 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) { {{#zcl_command_arguments}} case {{index}}: - if ({{asSymbol label}}Exists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } {{#if (isOctetString type)}} { const uint8_t * data = nullptr; @@ -43,11 +55,6 @@ while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) {{else}} TLVUnpackError = aDataTlv.Get({{asSymbol label}}); {{/if}} - if (CHIP_NO_ERROR == TLVUnpackError) - { - {{asSymbol label}}Exists = true; - validArgumentCount++; - } break; {{/zcl_command_arguments}} default: @@ -55,37 +62,26 @@ while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, TLV::TagNumFromTag(aDataTlv.GetTag()), 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; -} -else -{ - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, 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}} {{#if (zcl_command_arguments_count this.id)}} -// TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && {{zcl_command_arguments_count this.id}} == validArgumentCount) { {{/if}} // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAf{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback(apCommandObj{{#zcl_command_arguments}}, {{#if (isCharString type)}}const_cast({{asSymbol label}}){{else}}{{asSymbol label}}{{/if}}{{/zcl_command_arguments}}); +return; {{#if (zcl_command_arguments_count this.id)}} } -else -{ - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress(Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, {{zcl_command_arguments_count this.id}}, validArgumentCount, TLVError, TLVUnpackError); -} {{/if}} diff --git a/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt b/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt index 1f06fe83c3578f..2da277d5b53541 100644 --- a/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt +++ b/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt @@ -28,6 +28,15 @@ namespace {{asCamelCased name false}} { void Dispatch{{asCamelCased side false}}Command(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; {{#if (user_cluster_has_enabled_manufacturer_command name side)}} {{else}} {{/if}} @@ -51,10 +60,17 @@ void Dispatch{{asCamelCased side false}}Command(app::Command * apCommandObj, Com apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_{{asDelimitedMacro define}}_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, {{zcl_command_arguments_count this.id}}, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } diff --git a/src/controller/java/AndroidCommandHandler.cpp b/src/controller/java/AndroidCommandHandler.cpp new file mode 100644 index 00000000000000..df64e385a93171 --- /dev/null +++ b/src/controller/java/AndroidCommandHandler.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +namespace chip { +namespace app { + +void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId, + chip::TLV::TLVReader & aReader, Command * apCommandObj) +{ + ChipLogDetail(Controller, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId, + aCommandId, aEndPointId); + ChipLogError( + Controller, + "Default DispatchSingleClusterCommand is called, this should be replaced by actual dispatched for cluster commands"); +} + +} // namespace app +} // namespace chip diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index 121f662795435d..20dce8e7da8317 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -28,6 +28,7 @@ shared_library("jni") { "AndroidBleConnectionDelegate.h", "AndroidBlePlatformDelegate.cpp", "AndroidBlePlatformDelegate.h", + "AndroidCommandHandler.cpp", "AndroidDeviceControllerWrapper.cpp", "AndroidDeviceControllerWrapper.h", "AndroidKeyValueStoreManagerImpl.cpp", From 73adebcf174deea8053cd01c501bef8e6ecefa4d Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Fri, 23 Apr 2021 14:22:49 +0200 Subject: [PATCH 05/17] Add IM related files to be built under darwin --- src/darwin/Framework/CHIP.xcodeproj/project.pbxproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj b/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj index c362b373e347b2..00469e1933986d 100644 --- a/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 1E1F24992636F84000FA0EA9 /* CHIPClusters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E1F24972636F84000FA0EA9 /* CHIPClusters.cpp */; }; 1E9BD1C72621AFF100FC3246 /* attribute-size.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E9BD1C62621AFF100FC3246 /* attribute-size.cpp */; }; 1EB41B7B263C4CC60048E4C1 /* CHIPClustersTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EB41B7A263C4CC60048E4C1 /* CHIPClustersTests.m */; }; + 1EBCAE982632D69F007415A3 /* IMClusterCommandHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EBCAE972632D69F007415A3 /* IMClusterCommandHandler.cpp */; }; + 1EBCAE9A2632D6E0007415A3 /* ember-compatibility-functions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EBCAE992632D6E0007415A3 /* ember-compatibility-functions.cpp */; }; 1EC4CE3A25CC263E00D7304F /* reporting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EC4CE3825CC263E00D7304F /* reporting.cpp */; }; 1EC4CE3B25CC263E00D7304F /* reporting-default-configuration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EC4CE3925CC263E00D7304F /* reporting-default-configuration.cpp */; }; 1EC4CE3D25CC265200D7304F /* DataModelHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EC4CE3C25CC265200D7304F /* DataModelHandler.cpp */; }; @@ -79,6 +81,8 @@ 1E1F24972636F84000FA0EA9 /* CHIPClusters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CHIPClusters.cpp; path = gen/CHIPClusters.cpp; sourceTree = ""; }; 1E9BD1C62621AFF100FC3246 /* attribute-size.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "attribute-size.cpp"; path = "gen/attribute-size.cpp"; sourceTree = ""; }; 1EB41B7A263C4CC60048E4C1 /* CHIPClustersTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CHIPClustersTests.m; sourceTree = ""; }; + 1EBCAE972632D69F007415A3 /* IMClusterCommandHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IMClusterCommandHandler.cpp; path = gen/IMClusterCommandHandler.cpp; sourceTree = ""; }; + 1EBCAE992632D6E0007415A3 /* ember-compatibility-functions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "ember-compatibility-functions.cpp"; path = "../../../app/util/ember-compatibility-functions.cpp"; sourceTree = ""; }; 1EC4CE3825CC263E00D7304F /* reporting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = reporting.cpp; path = ../../../app/reporting/reporting.cpp; sourceTree = ""; }; 1EC4CE3925CC263E00D7304F /* reporting-default-configuration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "reporting-default-configuration.cpp"; path = "../../../app/reporting/reporting-default-configuration.cpp"; sourceTree = ""; }; 1EC4CE3C25CC265200D7304F /* DataModelHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataModelHandler.cpp; path = ../../../app/util/DataModelHandler.cpp; sourceTree = ""; }; @@ -160,6 +164,8 @@ 1EC4CE3525CC259700D7304F /* CHIPApp */ = { isa = PBXGroup; children = ( + 1EBCAE992632D6E0007415A3 /* ember-compatibility-functions.cpp */, + 1ED0B8CB260125E100D19DB5 /* media-playback-client.cpp */, 1EC4CE6125CC271B00D7304F /* af-event.cpp */, 1EC4CE4925CC267700D7304F /* af-main-common.cpp */, 1EC4CE4125CC267600D7304F /* attribute-size.cpp */, @@ -186,6 +192,7 @@ children = ( 1E1F24972636F84000FA0EA9 /* CHIPClusters.cpp */, 1E1F24962636F84000FA0EA9 /* CHIPClusters.h */, + 1EBCAE972632D69F007415A3 /* IMClusterCommandHandler.cpp */, 1E9BD1C62621AFF100FC3246 /* attribute-size.cpp */, 1EC4CE6325CC276600D7304F /* CHIPClustersObjc.h */, 1EC4CE5A25CC26E900D7304F /* call-command-handler.cpp */, @@ -437,6 +444,7 @@ 1EC4CE4E25CC267700D7304F /* attribute-size.cpp in Sources */, 1EC4CE4D25CC267700D7304F /* process-global-message.cpp in Sources */, 1EC4CE5125CC267700D7304F /* message.cpp in Sources */, + 1EBCAE982632D69F007415A3 /* IMClusterCommandHandler.cpp in Sources */, 1EC4CE5D25CC26E900D7304F /* CHIPClustersObjc.mm in Sources */, 1E9BD1C72621AFF100FC3246 /* attribute-size.cpp in Sources */, B2E0D7B3245B0B5C003C5B48 /* CHIPError.mm in Sources */, @@ -450,6 +458,7 @@ 1EC4CE5525CC267700D7304F /* attribute-table.cpp in Sources */, B2E0D7B9245B0B5C003C5B48 /* CHIPSetupPayload.mm in Sources */, B2E0D7B6245B0B5C003C5B48 /* CHIPManualSetupPayloadParser.mm in Sources */, + 1EBCAE9A2632D6E0007415A3 /* ember-compatibility-functions.cpp in Sources */, 1EC4CE6025CC26E900D7304F /* CHIPClientCallbacks.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From 3f3630ab0507e7ec61b8869e297c4fdc14dc3f6d Mon Sep 17 00:00:00 2001 From: Song Guo Date: Tue, 27 Apr 2021 16:38:43 +0800 Subject: [PATCH 06/17] Add DeviceControllerIMDelegate to make current applications work --- .../app/CHIPClientCallbacks-src.zapt | 46 ++++++++++ .../templates/app/CHIPClientCallbacks.zapt | 7 ++ src/controller/CHIPDevice.cpp | 17 ++++ src/controller/CHIPDevice.h | 4 + src/controller/CHIPDeviceController.cpp | 83 ++++++++++++++++++- src/controller/CHIPDeviceController.h | 21 +++++ 6 files changed, 177 insertions(+), 1 deletion(-) diff --git a/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt b/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt index b7e73e39ab7eb0..22b04459c2fc77 100644 --- a/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt @@ -3,6 +3,8 @@ {{#if (chip_has_client_clusters)}} #include "gen/CHIPClientCallbacks.h" +#include + #include "gen/enums.h" #include #include @@ -64,6 +66,29 @@ using namespace ::chip; return true; \ } + +#define GET_CLUSTER_RESPONSE_CALLBACKS(name) \ + Callback::Cancelable * onSuccessCallback = nullptr; \ + Callback::Cancelable * onFailureCallback = nullptr; \ + NodeId sourceIdentifier = reinterpret_cast(commandObj); \ + /* #6559: Currently, we only have one commands for the IMInvokeCommands and to a device, so the seqNum is always set to 0. */ \ + CHIP_ERROR err = gCallbacks.GetResponseCallback(sourceIdentifier, 0, &onSuccessCallback, &onFailureCallback); \ + \ + if (CHIP_NO_ERROR != err) \ + { \ + if (onSuccessCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing success callback", name); \ + } \ + \ + if (onFailureCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing failure callback", name); \ + } \ + \ + return true; \ + } + #define GET_REPORT_CALLBACK(name) \ Callback::Cancelable * onReportCallback = nullptr; \ CHIP_ERROR err = gCallbacks.GetReportCallback(sourceId, endpointId, clusterId, attributeId, &onReportCallback); \ @@ -230,6 +255,27 @@ bool emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, Em return true; } +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status) +{ + ChipLogProgress(Zcl, "DefaultResponse:"); + ChipLogProgress(Zcl, " Transaction: %p", commandObj); + LogStatus(status); + + GET_CLUSTER_RESPONSE_CALLBACKS("emberAfDefaultResponseCallback"); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); + cb->mCall(cb->mContext); + } + else + { + Callback::Callback * cb = Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, static_cast(status)); + } + + return true; +} + bool emberAfReadAttributesResponseCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) { ChipLogProgress(Zcl, "ReadAttributesResponse:"); diff --git a/src/app/zap-templates/templates/app/CHIPClientCallbacks.zapt b/src/app/zap-templates/templates/app/CHIPClientCallbacks.zapt index fd93e1eed281b1..2a54168c869d7c 100644 --- a/src/app/zap-templates/templates/app/CHIPClientCallbacks.zapt +++ b/src/app/zap-templates/templates/app/CHIPClientCallbacks.zapt @@ -5,7 +5,14 @@ #include #include +#include #include +#include + +// Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus +// instead of IM status code. +// #6308 should handle IM error code on the application side, either modify this function or remove this. +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status); // Global Response Callbacks typedef void (*DefaultSuccessCallback)(void * context); diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 506ba229a98685..b62263b322a812 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -398,6 +398,23 @@ void Device::CancelResponseHandler(uint8_t seqNum) mCallbacksMgr.CancelResponseCallback(mDeviceId, seqNum); } +void Device::AddIMResponseHandler(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) +{ + // This is a bit tricky, we try to assume that chip::NodeId is uint64_t so the pointer can be used as a NodeId for CallbackMgr. + static_assert(std::is_same::value, "chip::NodeId is not uint64_t"); + chip::NodeId transactionId = reinterpret_cast(static_cast(mCommandSender)); + mCallbacksMgr.AddResponseCallback(transactionId, 0 /* seqNum, always 0 for IM before #6559 */, onSuccessCallback, + onFailureCallback); +} + +void Device::CancelIMResponseHandler() +{ + // This is a bit tricky, we try to assume that chip::NodeId is uint64_t so the pointer can be used as a NodeId for CallbackMgr. + static_assert(std::is_same::value, "chip::NodeId is not uint64_t"); + chip::NodeId transactionId = reinterpret_cast(static_cast(mCommandSender)); + mCallbacksMgr.CancelResponseCallback(transactionId, 0 /* seqNum, always 0 for IM before #6559 */); +} + void Device::AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute, Callback::Cancelable * onReportCallback) { diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index c7141cc06500e9..d6a232a86809de 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -328,6 +328,10 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate void CancelResponseHandler(uint8_t seqNum); void AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute, Callback::Cancelable * onReportCallback); + // This two functions are pretty tricky, it is used to bridge the response + void AddIMResponseHandler(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); + void CancelIMResponseHandler(); + private: enum class ConnectionState { diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 0a318158149353..731a5c92a0342a 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,8 @@ #include #endif +#include + #include #include #include @@ -69,6 +72,14 @@ using namespace chip::Inet; using namespace chip::System; +// For some applications those does not implement IMDelegate, the DeviceControllerInteractionModelDelegate will dispatch the +// response to IMDefaultResponseCallback CHIPClientCallbacks, for the applications those implemented IMDelegate, this function will +// not be used. +bool __attribute__((weak)) IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status) +{ + return false; +} + namespace chip { namespace Controller { @@ -179,7 +190,15 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, ControllerInitParams par err = mExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::TempZCL::Id, this); SuccessOrExit(err); - err = chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, params.imDelegate); + if (params.imDelegate != nullptr) + { + err = chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, params.imDelegate); + } + else + { + mDefaultIMDelegate = chip::Platform::New(); + err = chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, mDefaultIMDelegate); + } SuccessOrExit(err); mExchangeMgr->SetDelegate(this); @@ -244,6 +263,12 @@ CHIP_ERROR DeviceController::Shutdown() mTransportMgr = nullptr; } + if (mDefaultIMDelegate != nullptr) + { + chip::Platform::Delete(mDefaultIMDelegate); + mDefaultIMDelegate = nullptr; + } + mAdmins.ReleaseAdminId(mAdminId); #if CHIP_DEVICE_CONFIG_ENABLE_MDNS @@ -1073,6 +1098,62 @@ void DeviceCommissioner::OnSessionEstablishmentTimeoutCallback(System::Layer * a reinterpret_cast(aAppState)->OnSessionEstablishmentTimeout(); } +CHIP_ERROR DeviceControllerInteractionModelDelegate::CommandResponseStatus( + const app::CommandSender * apCommandSender, const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, + const uint32_t aProtocolId, const uint16_t aProtocolCode, chip::EndpointId aEndpointId, const chip::ClusterId aClusterId, + chip::CommandId aCommandId, uint8_t aCommandIndex) +{ + // #6308, #6559: Invoking success Callbacks in `CommandResponseProcessed` is not desired, but this is used to met current + // requirement of current callback framework that we should be able to send another command once ResponseCallback is called. By + // resolving #6308, the app can wait for the right event, and by #6559 the app can send command in a now command sender. + VerifyOrReturnError(aProtocolCode != 0, CHIP_NO_ERROR); + + // Generally IM has more detailed errors than ember library, here we always use the, the actual handling of the + // commands should implement full IMDelegate. + // #6308 By implement app side IM delegate, we should be able to accept detailed error codes. + // Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus + // instead of IM status code. + IMDefaultResponseCallback(apCommandSender, EMBER_ZCL_STATUS_FAILURE); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DeviceControllerInteractionModelDelegate::CommandResponseProtocolError(const app::CommandSender * apCommandSender, + uint8_t aCommandIndex) +{ + // Generally IM has more detailed errors than ember library, here we always use EMBER_ZCL_STATUS_FAILURE before #6308 is landed + // and the app can take care of these error codes, the actual handling of the commands should implement full IMDelegate. + // #6308: By implement app side IM delegate, we should be able to accept detailed error codes. + // Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus + // instead of IM status code. + IMDefaultResponseCallback(apCommandSender, EMBER_ZCL_STATUS_FAILURE); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DeviceControllerInteractionModelDelegate::CommandResponseError(const app::CommandSender * apCommandSender, + CHIP_ERROR aError) +{ + // Generally IM has more detailed errors than ember library, here we always use EMBER_ZCL_STATUS_FAILURE before #6308 is landed + // and the app can take care of these error codes, the actual handling of the commands should implement full IMDelegate. + // #6308: By implement app side IM delegate, we should be able to accept detailed error codes. + // Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus + // instead of IM status code. + IMDefaultResponseCallback(apCommandSender, EMBER_ZCL_STATUS_FAILURE); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DeviceControllerInteractionModelDelegate::CommandResponseProcessed(const app::CommandSender * apCommandSender) +{ + // #6308, #6559: Invoking Callbacks in `CommandResponseProcessed` is not desired, but this is used to met current requirement of + // current callback framework that we should be able to send another command once ResponseCallback is called. + // By resolving #6308, the app can wait for the right event, and by #6559 the app can send command in a now command sender. + IMDefaultResponseCallback(apCommandSender, EMBER_ZCL_STATUS_SUCCESS); + + return CHIP_NO_ERROR; +} + } // namespace Controller } // namespace chip diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 46da5e9a300ec6..2e7d521f3b3e14 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -121,6 +121,26 @@ struct CommissionerInitParams : public ControllerInitParams OperationalCredentialsDelegate * operationalCredentialsDelegate = nullptr; }; +/** + * @brief + * Used for make current OnSuccessCallback & OnFailureCallback works when interaction model landed, it will be removed + * after #6308 is landed. + */ +class DeviceControllerInteractionModelDelegate : public chip::app::InteractionModelDelegate +{ +public: + CHIP_ERROR CommandResponseStatus(const app::CommandSender * apCommandSender, + const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, const uint32_t aProtocolId, + const uint16_t aProtocolCode, chip::EndpointId aEndpointId, const chip::ClusterId aClusterId, + chip::CommandId aCommandId, uint8_t aCommandIndex) override; + + CHIP_ERROR CommandResponseProtocolError(const app::CommandSender * apCommandSender, uint8_t aCommandIndex) override; + + CHIP_ERROR CommandResponseError(const app::CommandSender * apCommandSender, CHIP_ERROR aError) override; + + CHIP_ERROR CommandResponseProcessed(const app::CommandSender * apCommandSender) override; +}; + /** * @brief * Controller applications can use this class to communicate with already paired CHIP devices. The @@ -228,6 +248,7 @@ class DLL_EXPORT DeviceController : public Messaging::ExchangeDelegate, SecureSessionMgr * mSessionMgr; Messaging::ExchangeManager * mExchangeMgr; PersistentStorageDelegate * mStorageDelegate; + DeviceControllerInteractionModelDelegate * mDefaultIMDelegate; #if CHIP_DEVICE_CONFIG_ENABLE_MDNS DeviceAddressUpdateDelegate * mDeviceAddressUpdateDelegate = nullptr; #endif From eba5d40f98e71a12a7f9ec0a0683f5ab13832bf1 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Fri, 7 May 2021 11:20:06 +0800 Subject: [PATCH 07/17] Add a comment for MfgSpecificPing --- src/app/zap-templates/zcl/clusters-extensions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/zap-templates/zcl/clusters-extensions.xml b/src/app/zap-templates/zcl/clusters-extensions.xml index 4dab11082ed374..e63a37993b4404 100644 --- a/src/app/zap-templates/zcl/clusters-extensions.xml +++ b/src/app/zap-templates/zcl/clusters-extensions.xml @@ -18,7 +18,7 @@ limitations under the License. - + From 0566db423057b54eff5c1eb2d3cf5a6c1e932672 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Wed, 28 Apr 2021 11:41:11 +0800 Subject: [PATCH 08/17] Add blocking=True in test script --- src/controller/python/test/mobile-device-test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/controller/python/test/mobile-device-test.py b/src/controller/python/test/mobile-device-test.py index b9e16427ae27b4..d0aa04fa9e99ec 100755 --- a/src/controller/python/test/mobile-device-test.py +++ b/src/controller/python/test/mobile-device-test.py @@ -92,7 +92,7 @@ def TestNetworkCommissioning(self, nodeid: int): self.devCtrl.ZCLSend("NetworkCommissioning", "AddThreadNetwork", nodeid, ENDPOINT_ID, GROUP_ID, { "operationalDataset": bytes.fromhex(TEST_THREAD_NETWORK_DATASET_TLV), "breadcrumb": 0, - "timeoutMs": 1000}) + "timeoutMs": 1000}, blocking=True) except Exception as ex: self.logger.exception("Failed to send AddThreadNetwork command") return False @@ -101,7 +101,7 @@ def TestNetworkCommissioning(self, nodeid: int): self.devCtrl.ZCLSend("NetworkCommissioning", "EnableNetwork", nodeid, ENDPOINT_ID, GROUP_ID, { "networkID": bytes.fromhex(TEST_THREAD_NETWORK_ID), "breadcrumb": 0, - "timeoutMs": 1000}) + "timeoutMs": 1000}, blocking=True) except Exception as ex: self.logger.exception("Failed to send EnableNetwork command") return False @@ -110,12 +110,12 @@ def TestNetworkCommissioning(self, nodeid: int): def TestOnOffCluster(self, nodeid: int): self.logger.info("Sending On/Off commands to device {}".format(nodeid)) try: - self.devCtrl.ZCLSend("OnOff", "On", nodeid, ENDPOINT_ID, GROUP_ID, {}) + self.devCtrl.ZCLSend("OnOff", "On", nodeid, ENDPOINT_ID, GROUP_ID, {}, blocking=True) except Exception as ex: self.logger.exception("Failed to send On command") return False try: - self.devCtrl.ZCLSend("OnOff", "Off", nodeid, ENDPOINT_ID, GROUP_ID, {}) + self.devCtrl.ZCLSend("OnOff", "Off", nodeid, ENDPOINT_ID, GROUP_ID, {}, blocking=True) except Exception as ex: self.logger.exception("Failed to send Off command") return False From 9d81055bbea36499b5b92c6f7a4cf6e20a61fdd0 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Mon, 3 May 2021 16:24:15 +0800 Subject: [PATCH 09/17] Update template upd python template Fix template --- .../test-cluster-server.cpp | 21 +++++++++++++- .../im_command_handler_cluster_commands.zapt | 3 +- .../app/CHIPClientCallbacks-src.zapt | 2 +- .../templates/app/CHIPClusters-src.zapt | 5 ++-- .../app/im-cluster-command-handler.zapt | 29 ++++++++++++++----- .../chip/python-CHIPClusters-cpp.zapt | 2 +- 6 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/app/clusters/test-cluster-server/test-cluster-server.cpp b/src/app/clusters/test-cluster-server/test-cluster-server.cpp index 9e657730b58aeb..d42e5cbf6aa88d 100644 --- a/src/app/clusters/test-cluster-server/test-cluster-server.cpp +++ b/src/app/clusters/test-cluster-server/test-cluster-server.cpp @@ -42,8 +42,9 @@ bool emberAfTestClusterClusterTestCallback(chip::app::Command *) return true; } -bool emberAfTestClusterClusterTestSpecificCallback(chip::app::Command *) +bool emberAfTestClusterClusterTestSpecificCallback(chip::app::Command * apCommandObj) { + CHIP_ERROR err = CHIP_NO_ERROR; uint8_t returnValue = 7; emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_TEST_CLUSTER_ID, ZCL_TEST_SPECIFIC_RESPONSE_COMMAND_ID, "u", returnValue); @@ -54,6 +55,24 @@ bool emberAfTestClusterClusterTestSpecificCallback(chip::app::Command *) ChipLogError(Zcl, "Test Cluster: failed to send TestSpecific response: 0x%x", sendStatus); } + if (apCommandObj != nullptr) + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_TEST_CLUSTER_ID, + ZCL_TEST_SPECIFIC_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + + SuccessOrExit(err = apCommandObj->PrepareCommand(&cmdParams)); + writer = apCommandObj->GetCommandDataElementTLVWriter(); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), returnValue)); + SuccessOrExit(err = apCommandObj->FinishCommand()); + } + +exit: + if (CHIP_NO_ERROR != err) + { + ChipLogError(Zcl, "Test Cluster: failed to send TestSpecific response: %x", err); + } return true; } diff --git a/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt b/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt index c67df9f1a6c09f..f9b25b11400730 100644 --- a/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt +++ b/src/app/zap-templates/partials/im_command_handler_cluster_commands.zapt @@ -80,8 +80,7 @@ if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && {{zcl_comman { {{/if}} // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. -emberAf{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback(apCommandObj{{#zcl_command_arguments}}, {{#if (isCharString type)}}const_cast({{asSymbol label}}){{else}}{{asSymbol label}}{{/if}}{{/zcl_command_arguments}}); -return; +wasHandled = emberAf{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback(apCommandObj{{#zcl_command_arguments}}, {{#if (isCharString type)}}const_cast({{asSymbol label}}){{else}}{{asSymbol label}}{{/if}}{{/zcl_command_arguments}}); {{#if (zcl_command_arguments_count this.id)}} } {{/if}} diff --git a/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt b/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt index 22b04459c2fc77..cd886046e52a40 100644 --- a/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt @@ -787,7 +787,7 @@ bool emberAf{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}} {{/if}} {{/zcl_command_arguments}} - GET_RESPONSE_CALLBACKS("{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback"); + GET_CLUSTER_RESPONSE_CALLBACKS("{{asCamelCased parent.name false}}Cluster{{asCamelCased name false}}Callback"); {{#zcl_command_arguments}} {{#if (isStrEqual label "status")}} diff --git a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt index ce7eb4ca622821..1bc5531fb82e21 100644 --- a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt @@ -20,8 +20,6 @@ namespace Controller { CHIP_ERROR {{asCamelCased clusterName false}}Cluster::{{asCamelCased name false}}(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback{{#chip_server_cluster_command_arguments}}, {{chipType}} {{asCamelCased label}}{{/chip_server_cluster_command_arguments}}) { VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, k{{asCamelCased name false}}CommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -42,6 +40,9 @@ CHIP_ERROR {{asCamelCased clusterName false}}Cluster::{{asCamelCased name false} ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // Note: This is a temporary solution before we fully support IM on application side, this line should be removed in the future. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); } diff --git a/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt b/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt index 2da277d5b53541..102ed2910e249e 100644 --- a/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt +++ b/src/app/zap-templates/templates/app/im-cluster-command-handler.zapt @@ -37,6 +37,7 @@ void Dispatch{{asCamelCased side false}}Command(app::Command * apCommandObj, Com uint32_t validArgumentCount = 0; uint32_t expectArgumentCount = 0; uint32_t currentDecodeTagId = 0; + bool wasHandled = false; {{#if (user_cluster_has_enabled_manufacturer_command name side)}} {{else}} {{/if}} @@ -57,7 +58,12 @@ void Dispatch{{asCamelCased side false}}Command(app::Command * apCommandObj, Com {{/all_user_cluster_commands}} default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_{{asDelimitedMacro define}}_ID, + aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_{{asDelimitedMacro define}}_ID); return; @@ -65,11 +71,16 @@ void Dispatch{{asCamelCased side false}}Command(app::Command * apCommandObj, Com } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_{{asDelimitedMacro define}}_ID, + aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress(Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, {{zcl_command_arguments_count this.id}}, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); } } @@ -92,16 +103,20 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC { {{#all_user_clusters}} {{#if (user_cluster_has_enabled_command name side)}} - {{#unless (isClient side) }} case ZCL_{{asDelimitedMacro define}}_ID : clusters::{{asCamelCased name false}}::Dispatch{{asCamelCased side false}}Command(apCommandObj, aCommandId, aEndPointId, aReader); break; - {{/unless}} {{/if}} {{/all_user_clusters}} default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, + aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; diff --git a/src/app/zap-templates/templates/chip/python-CHIPClusters-cpp.zapt b/src/app/zap-templates/templates/chip/python-CHIPClusters-cpp.zapt index fd45c261a030cc..dd089fa5f3abdb 100644 --- a/src/app/zap-templates/templates/chip/python-CHIPClusters-cpp.zapt +++ b/src/app/zap-templates/templates/chip/python-CHIPClusters-cpp.zapt @@ -80,7 +80,7 @@ CHIP_ERROR chip_ime_AppendCommand_{{asCamelCased clusterName false}}_{{asCamelCa VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::{{asCamelCased clusterName false}}Cluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.{{asCamelCased name false}}(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(){{#chip_server_cluster_command_arguments}}, {{#if (isString type)}}chip::ByteSpan({{asCamelCased label}}, {{asCamelCased label}}_Len){{else}}{{asCamelCased label}}{{/if}} + return cluster.{{asCamelCased name false}}(nullptr, nullptr{{#chip_server_cluster_command_arguments}}, {{#if (isString type)}}chip::ByteSpan({{asCamelCased label}}, {{asCamelCased label}}_Len){{else}}{{asCamelCased label}}{{/if}} {{/chip_server_cluster_command_arguments}}); } {{/chip_server_cluster_commands}} From 21f909a748823db8d77061c2b0416f5c4d65c347 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Thu, 6 May 2021 11:45:35 +0800 Subject: [PATCH 10/17] Disable CRMP for command sender --- src/app/CommandHandler.cpp | 2 +- src/app/CommandSender.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp index 480efaa72039d8..70118a653cb8bd 100644 --- a/src/app/CommandHandler.cpp +++ b/src/app/CommandHandler.cpp @@ -62,7 +62,7 @@ CHIP_ERROR CommandHandler::SendCommandResponse() VerifyOrExit(mpExchangeCtx != nullptr, err = CHIP_ERROR_INCORRECT_STATE); err = mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::InvokeCommandResponse, std::move(mCommandMessageBuf), - Messaging::SendFlags(Messaging::SendMessageFlags::kNone)); + Messaging::SendFlags(Messaging::SendMessageFlags::kNoAutoRequestAck)); SuccessOrExit(err); MoveToState(CommandState::Sending); diff --git a/src/app/CommandSender.cpp b/src/app/CommandSender.cpp index fefd28e69cb490..4a87e0fa7bc103 100644 --- a/src/app/CommandSender.cpp +++ b/src/app/CommandSender.cpp @@ -50,8 +50,9 @@ CHIP_ERROR CommandSender::SendCommandRequest(NodeId aNodeId, Transport::AdminId VerifyOrExit(mpExchangeCtx != nullptr, err = CHIP_ERROR_NO_MEMORY); mpExchangeCtx->SetResponseTimeout(kImMessageTimeoutMsec); - err = mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::InvokeCommandRequest, std::move(mCommandMessageBuf), - Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse)); + err = mpExchangeCtx->SendMessage( + Protocols::InteractionModel::MsgType::InvokeCommandRequest, std::move(mCommandMessageBuf), + Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse).Set(Messaging::SendMessageFlags::kNoAutoRequestAck)); SuccessOrExit(err); MoveToState(CommandState::Sending); From 96505abcff5f3c3af7c6897d7404232c444845d0 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Thu, 6 May 2021 12:04:42 +0800 Subject: [PATCH 11/17] Fix TestCluster --- .../test-cluster-server.cpp | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/app/clusters/test-cluster-server/test-cluster-server.cpp b/src/app/clusters/test-cluster-server/test-cluster-server.cpp index d42e5cbf6aa88d..47bafcf3eb334e 100644 --- a/src/app/clusters/test-cluster-server/test-cluster-server.cpp +++ b/src/app/clusters/test-cluster-server/test-cluster-server.cpp @@ -44,29 +44,19 @@ bool emberAfTestClusterClusterTestCallback(chip::app::Command *) bool emberAfTestClusterClusterTestSpecificCallback(chip::app::Command * apCommandObj) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; uint8_t returnValue = 7; - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_TEST_CLUSTER_ID, - ZCL_TEST_SPECIFIC_RESPONSE_COMMAND_ID, "u", returnValue); - EmberStatus sendStatus = emberAfSendResponse(); - if (EMBER_SUCCESS != sendStatus) - { - ChipLogError(Zcl, "Test Cluster: failed to send TestSpecific response: 0x%x", sendStatus); - } + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_TEST_CLUSTER_ID, + ZCL_TEST_SPECIFIC_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; - if (apCommandObj != nullptr) - { - app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_TEST_CLUSTER_ID, - ZCL_TEST_SPECIFIC_RESPONSE_COMMAND_ID, - (chip::app::CommandPathFlags::kEndpointIdValid) }; - TLV::TLVWriter * writer = nullptr; + VerifyOrExit(apCommandObj != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - SuccessOrExit(err = apCommandObj->PrepareCommand(&cmdParams)); - writer = apCommandObj->GetCommandDataElementTLVWriter(); - SuccessOrExit(err = writer->Put(TLV::ContextTag(0), returnValue)); - SuccessOrExit(err = apCommandObj->FinishCommand()); - } + SuccessOrExit(err = apCommandObj->PrepareCommand(&cmdParams)); + writer = apCommandObj->GetCommandDataElementTLVWriter(); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), returnValue)); + SuccessOrExit(err = apCommandObj->FinishCommand()); exit: if (CHIP_NO_ERROR != err) From 57e1a82f9a3856375b5094c8db38c32424804afb Mon Sep 17 00:00:00 2001 From: Song Guo Date: Thu, 6 May 2021 19:18:14 +0800 Subject: [PATCH 12/17] Update comment --- src/app/zap-templates/templates/app/CHIPClusters-src.zapt | 2 +- src/controller/CHIPDevice.cpp | 8 ++++++-- src/controller/CHIPDevice.h | 5 ++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt index 1bc5531fb82e21..7475968806c345 100644 --- a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt @@ -40,7 +40,7 @@ CHIP_ERROR {{asCamelCased clusterName false}}Cluster::{{asCamelCased name false} ReturnErrorOnFailure(ZCLcommand->FinishCommand()); - // Note: This is a temporary solution before we fully support IM on application side, this line should be removed in the future. + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); return mDevice->SendCommands(); diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index b62263b322a812..56997b956e89fe 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -400,7 +400,9 @@ void Device::CancelResponseHandler(uint8_t seqNum) void Device::AddIMResponseHandler(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { - // This is a bit tricky, we try to assume that chip::NodeId is uint64_t so the pointer can be used as a NodeId for CallbackMgr. + // We are using the pointer to command sender object as the identifier of command transactions. This makes sense as long as + // there are only one active command transaction on one command sender object. This is a bit tricky, we try to assume that + // chip::NodeId is uint64_t so the pointer can be used as a NodeId for CallbackMgr. static_assert(std::is_same::value, "chip::NodeId is not uint64_t"); chip::NodeId transactionId = reinterpret_cast(static_cast(mCommandSender)); mCallbacksMgr.AddResponseCallback(transactionId, 0 /* seqNum, always 0 for IM before #6559 */, onSuccessCallback, @@ -409,7 +411,9 @@ void Device::AddIMResponseHandler(Callback::Cancelable * onSuccessCallback, Call void Device::CancelIMResponseHandler() { - // This is a bit tricky, we try to assume that chip::NodeId is uint64_t so the pointer can be used as a NodeId for CallbackMgr. + // We are using the pointer to command sender object as the identifier of command transactions. This makes sense as long as + // there are only one active command transaction on one command sender object. This is a bit tricky, we try to assume that + // chip::NodeId is uint64_t so the pointer can be used as a NodeId for CallbackMgr. static_assert(std::is_same::value, "chip::NodeId is not uint64_t"); chip::NodeId transactionId = reinterpret_cast(static_cast(mCommandSender)); mCallbacksMgr.CancelResponseCallback(transactionId, 0 /* seqNum, always 0 for IM before #6559 */); diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index d6a232a86809de..52a29c8349d6af 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -328,7 +328,10 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate void CancelResponseHandler(uint8_t seqNum); void AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute, Callback::Cancelable * onReportCallback); - // This two functions are pretty tricky, it is used to bridge the response + // This two functions are pretty tricky, it is used to bridge the response, we need to implement interaction model delegate on + // the app side instead of register callbacks here. The IM delegate can provide more infomation then callback and it is + // type-safe. + // TODO: Implement interaction model delegate in the application. void AddIMResponseHandler(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); void CancelIMResponseHandler(); From a69805b0ec8d927fb91eb1ae67229c1c7103006d Mon Sep 17 00:00:00 2001 From: Song Guo Date: Tue, 11 May 2021 03:28:13 +0800 Subject: [PATCH 13/17] Run Codegen --- .../gen/IMClusterCommandHandler.cpp | 6682 ++++++----------- .../gen/IMClusterCommandHandler.cpp | 1649 ++-- .../chip-tool/gen/CHIPClientCallbacks.cpp | 177 +- examples/chip-tool/gen/CHIPClientCallbacks.h | 7 + examples/chip-tool/gen/CHIPClusters.cpp | 1379 +--- .../chip-tool/gen/IMClusterCommandHandler.cpp | 5042 +++++-------- .../gen/IMClusterCommandHandler.cpp | 1649 ++-- .../gen/IMClusterCommandHandler.cpp | 1068 +-- .../pump-common/gen/CHIPClientCallbacks.cpp | 47 + .../pump-common/gen/CHIPClientCallbacks.h | 7 + .../pump-app/pump-common/gen/CHIPClusters.cpp | 22 +- .../gen/IMClusterCommandHandler.cpp | 1991 ++--- .../pump-app/pump-common/gen/attribute-id.h | 19 + .../pump-common/gen/client-command-macro.h | 74 + .../pump-app/pump-common/gen/cluster-id.h | 3 + .../pump-app/pump-common/gen/command-id.h | 8 + examples/pump-app/pump-common/gen/enums.h | 22 + .../pump-app/pump-common/gen/print-cluster.h | 8 + .../gen/CHIPClientCallbacks.cpp | 47 + .../gen/CHIPClientCallbacks.h | 7 + .../gen/CHIPClusters.cpp | 33 +- .../gen/IMClusterCommandHandler.cpp | 1030 +-- .../pump-controller-common/gen/attribute-id.h | 19 + .../gen/client-command-macro.h | 74 + .../pump-controller-common/gen/cluster-id.h | 3 + .../pump-controller-common/gen/command-id.h | 8 + .../pump-controller-common/gen/enums.h | 22 + .../gen/print-cluster.h | 8 + .../main/gen/IMClusterCommandHandler.cpp | 1030 +-- .../tv-common/gen/IMClusterCommandHandler.cpp | 2179 +++--- .../common/gen/IMClusterCommandHandler.cpp | 1079 +-- .../python/chip/clusters/CHIPClusters.cpp | 330 +- .../python/gen/CHIPClientCallbacks.cpp | 184 +- .../python/gen/CHIPClientCallbacks.h | 7 + src/controller/python/gen/CHIPClusters.cpp | 1483 +--- .../python/gen/IMClusterCommandHandler.cpp | 5091 +++++-------- src/controller/python/gen/callback.h | 3 - .../CHIP/gen/CHIPClientCallbacks.cpp | 141 +- .../Framework/CHIP/gen/CHIPClientCallbacks.h | 7 + .../Framework/CHIP/gen/CHIPClusters.cpp | 1075 +-- .../CHIP/gen/IMClusterCommandHandler.cpp | 3526 ++++----- 41 files changed, 14180 insertions(+), 23060 deletions(-) diff --git a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp index 10d457ab64aa6f..414ac200b25a15 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp @@ -43,46 +43,61 @@ namespace BarrierControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_BARRIER_CONTROL_GO_TO_PERCENT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t percentOpen; - bool percentOpenExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (percentOpenExists) + 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; } - TLVUnpackError = aDataTlv.Get(percentOpen); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - percentOpenExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(percentOpen); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -92,42 +107,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfBarrierControlClusterBarrierControlGoToPercentCallback(apCommandObj, percentOpen); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfBarrierControlClusterBarrierControlGoToPercentCallback(apCommandObj, percentOpen); } break; } case ZCL_BARRIER_CONTROL_STOP_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj); + wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_BARRIER_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_BARRIER_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_BARRIER_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace BarrierControl @@ -136,18 +156,46 @@ namespace Basic { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_BASIC_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_BASIC_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_BASIC_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Basic @@ -156,94 +204,73 @@ namespace Binding { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_BIND_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::NodeId nodeId; - bool nodeIdExists = false; chip::GroupId groupId; - bool groupIdExists = false; chip::EndpointId endpointId; - bool endpointIdExists = false; chip::ClusterId clusterId; - bool clusterIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (nodeIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(nodeId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - nodeIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(nodeId); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (endpointIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endpointId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endpointIdExists = true; - validArgumentCount++; - } break; case 3: - if (clusterIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(clusterId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - clusterIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -253,112 +280,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfBindingClusterBindCallback(apCommandObj, nodeId, groupId, endpointId, clusterId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfBindingClusterBindCallback(apCommandObj, nodeId, groupId, endpointId, clusterId); } break; } case ZCL_UNBIND_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::NodeId nodeId; - bool nodeIdExists = false; chip::GroupId groupId; - bool groupIdExists = false; chip::EndpointId endpointId; - bool endpointIdExists = false; chip::ClusterId clusterId; - bool clusterIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (nodeIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(nodeId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - nodeIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(nodeId); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (endpointIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endpointId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endpointIdExists = true; - validArgumentCount++; - } break; case 3: - if (clusterIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(clusterId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - clusterIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -368,36 +351,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfBindingClusterUnbindCallback(apCommandObj, nodeId, groupId, endpointId, clusterId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, nodeId, groupId, endpointId, clusterId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_BINDING_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_BINDING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_BINDING_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Binding @@ -406,94 +394,73 @@ namespace ColorControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_MOVE_COLOR_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; int16_t rateX; - bool rateXExists = false; int16_t rateY; - bool rateYExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (rateXExists) + 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; } - TLVUnpackError = aDataTlv.Get(rateX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - rateXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(rateX); break; case 1: - if (rateYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rateY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateYExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -503,144 +470,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveColorCallback(apCommandObj, rateX, rateY, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveColorCallback(apCommandObj, rateX, rateY, optionsMask, optionsOverride); } break; } case ZCL_MOVE_COLOR_TEMPERATURE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t moveMode; - bool moveModeExists = false; uint16_t rate; - bool rateExists = false; uint16_t colorTemperatureMinimum; - bool colorTemperatureMinimumExists = false; uint16_t colorTemperatureMaximum; - bool colorTemperatureMaximumExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (colorTemperatureMinimumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMinimumExists = true; - validArgumentCount++; - } break; case 3: - if (colorTemperatureMaximumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMaximumExists = true; - validArgumentCount++; - } break; case 4: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 5: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -650,113 +549,69 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveColorTemperatureCallback(apCommandObj, moveMode, rate, colorTemperatureMinimum, - colorTemperatureMaximum, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveColorTemperatureCallback( + apCommandObj, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); } break; } case ZCL_MOVE_HUE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -766,112 +621,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveHueCallback(apCommandObj, moveMode, rate, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveHueCallback(apCommandObj, moveMode, rate, optionsMask, optionsOverride); } break; } case ZCL_MOVE_SATURATION_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -881,128 +692,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveSaturationCallback(apCommandObj, moveMode, rate, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfColorControlClusterMoveSaturationCallback(apCommandObj, moveMode, rate, optionsMask, optionsOverride); } break; } case ZCL_MOVE_TO_COLOR_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint16_t colorX; - bool colorXExists = false; uint16_t colorY; - bool colorYExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (colorXExists) + 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; } - TLVUnpackError = aDataTlv.Get(colorX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - colorXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(colorX); break; case 1: - if (colorYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorYExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1012,113 +768,69 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveToColorCallback(apCommandObj, colorX, colorY, transitionTime, optionsMask, - optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveToColorCallback(apCommandObj, colorX, colorY, transitionTime, + optionsMask, optionsOverride); } break; } case ZCL_MOVE_TO_COLOR_TEMPERATURE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t colorTemperature; - bool colorTemperatureExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (colorTemperatureExists) + 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; } - TLVUnpackError = aDataTlv.Get(colorTemperature); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - colorTemperatureExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(colorTemperature); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1128,129 +840,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveToColorTemperatureCallback(apCommandObj, colorTemperature, transitionTime, - optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveToColorTemperatureCallback(apCommandObj, colorTemperature, + transitionTime, optionsMask, optionsOverride); } break; } case ZCL_MOVE_TO_HUE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t hue; - bool hueExists = false; uint8_t direction; - bool directionExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (hueExists) + 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; } - TLVUnpackError = aDataTlv.Get(hue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - hueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(hue); break; case 1: - if (directionExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(direction); - if (CHIP_NO_ERROR == TLVUnpackError) - { - directionExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1260,129 +916,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveToHueCallback(apCommandObj, hue, direction, transitionTime, optionsMask, - optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveToHueCallback(apCommandObj, hue, direction, transitionTime, optionsMask, + optionsOverride); } break; } case ZCL_MOVE_TO_HUE_AND_SATURATION_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t hue; - bool hueExists = false; uint8_t saturation; - bool saturationExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (hueExists) + 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; } - TLVUnpackError = aDataTlv.Get(hue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - hueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(hue); break; case 1: - if (saturationExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(saturation); - if (CHIP_NO_ERROR == TLVUnpackError) - { - saturationExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1392,113 +992,69 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveToHueAndSaturationCallback(apCommandObj, hue, saturation, transitionTime, optionsMask, - optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveToHueAndSaturationCallback(apCommandObj, hue, saturation, transitionTime, + optionsMask, optionsOverride); } break; } case ZCL_MOVE_TO_SATURATION_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t saturation; - bool saturationExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (saturationExists) + 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; } - TLVUnpackError = aDataTlv.Get(saturation); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - saturationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(saturation); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1508,129 +1064,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterMoveToSaturationCallback(apCommandObj, saturation, transitionTime, optionsMask, - optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterMoveToSaturationCallback(apCommandObj, saturation, transitionTime, + optionsMask, optionsOverride); } break; } case ZCL_STEP_COLOR_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; int16_t stepX; - bool stepXExists = false; int16_t stepY; - bool stepYExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepXExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepX); break; case 1: - if (stepYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepYExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1640,161 +1140,81 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterStepColorCallback(apCommandObj, stepX, stepY, transitionTime, optionsMask, - optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterStepColorCallback(apCommandObj, stepX, stepY, transitionTime, optionsMask, + optionsOverride); } break; } case ZCL_STEP_COLOR_TEMPERATURE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint8_t stepMode; - bool stepModeExists = false; uint16_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint16_t colorTemperatureMinimum; - bool colorTemperatureMinimumExists = false; uint16_t colorTemperatureMaximum; - bool colorTemperatureMaximumExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (colorTemperatureMinimumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMinimumExists = true; - validArgumentCount++; - } - break; - case 4: - if (colorTemperatureMaximumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } + break; + case 4: TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMaximumExists = true; - validArgumentCount++; - } break; case 5: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 6: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1804,130 +1224,74 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterStepColorTemperatureCallback(apCommandObj, stepMode, stepSize, transitionTime, - colorTemperatureMinimum, colorTemperatureMaximum, - optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterStepColorTemperatureCallback( + apCommandObj, stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, + optionsOverride); } break; } case ZCL_STEP_HUE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint8_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1937,129 +1301,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterStepHueCallback(apCommandObj, stepMode, stepSize, transitionTime, optionsMask, - optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterStepHueCallback(apCommandObj, stepMode, stepSize, transitionTime, + optionsMask, optionsOverride); } break; } case ZCL_STEP_SATURATION_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint8_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2069,81 +1377,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterStepSaturationCallback(apCommandObj, stepMode, stepSize, transitionTime, optionsMask, - optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterStepSaturationCallback(apCommandObj, stepMode, stepSize, transitionTime, + optionsMask, optionsOverride); } break; } case ZCL_STOP_MOVE_STEP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (optionsMaskExists) + 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; } - TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionsMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionsMask); break; case 1: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2153,36 +1441,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfColorControlClusterStopMoveStepCallback(apCommandObj, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfColorControlClusterStopMoveStepCallback(apCommandObj, optionsMask, optionsOverride); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_COLOR_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_COLOR_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_COLOR_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ColorControl @@ -2191,58 +1484,73 @@ namespace DoorLock { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_CLEAR_ALL_PINS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfDoorLockClusterClearAllPinsCallback(apCommandObj); + wasHandled = emberAfDoorLockClusterClearAllPinsCallback(apCommandObj); break; } case ZCL_CLEAR_ALL_RFIDS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj); + wasHandled = emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj); break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t scheduleId; - bool scheduleIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2252,64 +1560,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearHolidayScheduleCallback(apCommandObj, scheduleId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearHolidayScheduleCallback(apCommandObj, scheduleId); } break; } case ZCL_CLEAR_PIN_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2319,64 +1619,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearPinCallback(apCommandObj, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, userId); } break; } case ZCL_CLEAR_RFID_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2386,80 +1678,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearRfidCallback(apCommandObj, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, userId); } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2469,80 +1741,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearWeekdayScheduleCallback(apCommandObj, scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearWeekdayScheduleCallback(apCommandObj, scheduleId, userId); } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2552,64 +1804,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearYeardayScheduleCallback(apCommandObj, scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearYeardayScheduleCallback(apCommandObj, scheduleId, userId); } break; } case ZCL_GET_HOLIDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t scheduleId; - bool scheduleIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2619,64 +1863,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetHolidayScheduleCallback(apCommandObj, scheduleId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetHolidayScheduleCallback(apCommandObj, scheduleId); } break; } case ZCL_GET_LOG_RECORD_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t logIndex; - bool logIndexExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (logIndexExists) + 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; } - TLVUnpackError = aDataTlv.Get(logIndex); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logIndexExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logIndex); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2686,64 +1922,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetLogRecordCallback(apCommandObj, logIndex); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetLogRecordCallback(apCommandObj, logIndex); } break; } case ZCL_GET_PIN_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2753,64 +1981,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetPinCallback(apCommandObj, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetPinCallback(apCommandObj, userId); } break; } case ZCL_GET_RFID_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2820,64 +2040,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetRfidCallback(apCommandObj, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, userId); } break; } case ZCL_GET_USER_TYPE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2887,80 +2099,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, userId); } break; } case ZCL_GET_WEEKDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2970,80 +2162,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetWeekdayScheduleCallback(apCommandObj, scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetWeekdayScheduleCallback(apCommandObj, scheduleId, userId); } break; } case ZCL_GET_YEARDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3053,65 +2225,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetYeardayScheduleCallback(apCommandObj, scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetYeardayScheduleCallback(apCommandObj, scheduleId, userId); } break; } case ZCL_LOCK_DOOR_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * PIN; - bool PINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (PINExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(PIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - PINExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3121,112 +2285,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterLockDoorCallback(apCommandObj, const_cast(PIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterLockDoorCallback(apCommandObj, const_cast(PIN)); } break; } case ZCL_SET_HOLIDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t scheduleId; - bool scheduleIdExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 2: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 3: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3236,114 +2356,70 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetHolidayScheduleCallback(apCommandObj, scheduleId, localStartTime, localEndTime, - operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback(apCommandObj, scheduleId, localStartTime, + localEndTime, operatingModeDuringHoliday); } break; } case ZCL_SET_PIN_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3353,113 +2429,70 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetPinCallback(apCommandObj, userId, userStatus, userType, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfDoorLockClusterSetPinCallback(apCommandObj, userId, userStatus, userType, const_cast(pin)); } break; } case ZCL_SET_RFID_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * id; - bool idExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (idExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(id); - if (CHIP_NO_ERROR == TLVUnpackError) - { - idExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3469,80 +2502,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetRfidCallback(apCommandObj, userId, userStatus, userType, const_cast(id)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfDoorLockClusterSetRfidCallback(apCommandObj, userId, userStatus, userType, const_cast(id)); } break; } case ZCL_SET_USER_TYPE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3552,160 +2566,80 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, userId, userType); } break; } case ZCL_SET_WEEKDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - scheduleIdExists = true; - validArgumentCount++; - } - break; - case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } - break; - case 2: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } - break; - case 3: - if (startHourExists) + 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; } - TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - startHourExists = true; + 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(daysMask); + break; + case 3: + TLVUnpackError = aDataTlv.Get(startHour); break; case 4: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 5: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 6: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3715,113 +2649,69 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetWeekdayScheduleCallback(apCommandObj, scheduleId, userId, daysMask, startHour, startMinute, - endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback(apCommandObj, scheduleId, userId, daysMask, startHour, + startMinute, endHour, endMinute); } break; } case ZCL_SET_YEARDAY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3831,65 +2721,58 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetYeardayScheduleCallback(apCommandObj, scheduleId, userId, localStartTime, localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetYeardayScheduleCallback(apCommandObj, scheduleId, userId, localStartTime, + localEndTime); } break; } case ZCL_UNLOCK_DOOR_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * PIN; - bool PINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (PINExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(PIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - PINExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3899,81 +2782,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, const_cast(PIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, const_cast(PIN)); } break; } case ZCL_UNLOCK_WITH_TIMEOUT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t timeoutInSeconds; - bool timeoutInSecondsExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutInSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutInSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutInSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutInSeconds); break; case 1: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3983,36 +2846,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, timeoutInSeconds, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, timeoutInSeconds, const_cast(pin)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -4021,78 +2890,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4102,119 +2962,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4224,37 +3041,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -4263,63 +3085,66 @@ namespace Groups { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_GROUP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4329,81 +3154,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterAddGroupCallback(apCommandObj, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, groupId, const_cast(groupName)); } break; } case ZCL_ADD_GROUP_IF_IDENTIFYING_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4413,81 +3218,62 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterAddGroupIfIdentifyingCallback(apCommandObj, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGroupsClusterAddGroupIfIdentifyingCallback(apCommandObj, groupId, const_cast(groupName)); } break; } case ZCL_GET_GROUP_MEMBERSHIP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupCountExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupCountExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupCount); break; case 1: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4497,70 +3283,62 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, groupCount, groupList); } break; } case ZCL_REMOVE_ALL_GROUPS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj); + wasHandled = emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj); break; } case ZCL_REMOVE_GROUP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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) { - case 0: - if (groupIdExists) + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4570,64 +3348,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterRemoveGroupCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, groupId); } break; } case ZCL_VIEW_GROUP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4637,36 +3407,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterViewGroupCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, groupId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -4675,62 +3450,65 @@ namespace IasZone { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ZONE_ENROLL_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t enrollResponseCode; - bool enrollResponseCodeExists = false; uint8_t zoneId; - bool zoneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (enrollResponseCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(enrollResponseCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - enrollResponseCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(enrollResponseCode); break; case 1: - if (zoneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(zoneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - zoneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4740,36 +3518,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfIasZoneClusterZoneEnrollResponseCallback(apCommandObj, enrollResponseCode, zoneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfIasZoneClusterZoneEnrollResponseCallback(apCommandObj, enrollResponseCode, zoneId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_IAS_ZONE_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IAS_ZONE_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_IAS_ZONE_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace IasZone @@ -4778,46 +3561,61 @@ namespace Identify { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_IDENTIFY_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t identifyTime; - bool identifyTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (identifyTimeExists) + 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; } - TLVUnpackError = aDataTlv.Get(identifyTime); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - identifyTimeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(identifyTime); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4827,42 +3625,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfIdentifyClusterIdentifyCallback(apCommandObj, identifyTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, identifyTime); } break; } case ZCL_IDENTIFY_QUERY_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj); + wasHandled = emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -4871,94 +3674,73 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4968,112 +3750,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5083,80 +3821,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5166,80 +3885,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5249,128 +3948,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); } break; } case ZCL_STEP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5380,97 +4023,65 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, - optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, + optionOverride); } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5480,80 +4091,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); } break; } case ZCL_STOP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (optionMaskExists) + 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; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5563,42 +4154,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); } break; } case ZCL_STOP_WITH_ON_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -5607,24 +4203,52 @@ namespace LowPower { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_SLEEP_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfLowPowerClusterSleepCallback(apCommandObj); + wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LOW_POWER_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LOW_POWER_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LOW_POWER_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LowPower @@ -5633,82 +4257,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5718,120 +4332,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5841,100 +4410,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5944,100 +4481,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6047,64 +4552,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6114,100 +4612,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6217,100 +4682,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6320,100 +4753,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) - { - case 0: - if (operationalDatasetExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; - validArgumentCount++; - } - break; - case 1: - if (breadcrumbExists) + 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; } - TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - breadcrumbExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: + TLVUnpackError = aDataTlv.Get(breadcrumb); break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6423,121 +4823,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6547,36 +4901,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -6585,66 +4945,68 @@ namespace OtaSoftwareUpdateServer { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_APPLY_UPDATE_REQUEST_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; chip::ByteSpan updateToken; - bool updateTokenExists = false; uint32_t newVersion; - bool newVersionExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (updateTokenExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - updateToken = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - updateTokenExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + updateToken = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (newVersionExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(newVersion); - if (CHIP_NO_ERROR == TLVUnpackError) - { - newVersionExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6654,84 +5016,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOtaSoftwareUpdateServerClusterApplyUpdateRequestCallback(apCommandObj, updateToken, newVersion); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOtaSoftwareUpdateServerClusterApplyUpdateRequestCallback(apCommandObj, updateToken, newVersion); } break; } case ZCL_NOTIFY_UPDATE_APPLIED_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; chip::ByteSpan updateToken; - bool updateTokenExists = false; uint32_t currentVersion; - bool currentVersionExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (updateTokenExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - updateToken = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - updateTokenExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + updateToken = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (currentVersionExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(currentVersion); - if (CHIP_NO_ERROR == TLVUnpackError) - { - currentVersionExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6741,198 +5082,94 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOtaSoftwareUpdateServerClusterNotifyUpdateAppliedCallback(apCommandObj, updateToken, currentVersion); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfOtaSoftwareUpdateServerClusterNotifyUpdateAppliedCallback(apCommandObj, updateToken, currentVersion); } break; } case ZCL_QUERY_IMAGE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 9; uint16_t vendorId; - bool vendorIdExists = false; uint16_t productId; - bool productIdExists = false; uint16_t imageType; - bool imageTypeExists = false; uint16_t hardwareVersion; - bool hardwareVersionExists = false; uint32_t currentVersion; - bool currentVersionExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * protocolsSupported; - bool protocolsSupportedExists = false; const uint8_t * location; - bool locationExists = false; uint8_t clientCanConsent; - bool clientCanConsentExists = false; chip::ByteSpan metadataForServer; - bool metadataForServerExists = false; - uint32_t validArgumentCount = 0; + bool argExists[9]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (vendorIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 9) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(vendorId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - vendorIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(vendorId); break; case 1: - if (productIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(productId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - productIdExists = true; - validArgumentCount++; - } break; case 2: - if (imageTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(imageType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - imageTypeExists = true; - validArgumentCount++; - } break; case 3: - if (hardwareVersionExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(hardwareVersion); - if (CHIP_NO_ERROR == TLVUnpackError) - { - hardwareVersionExists = true; - validArgumentCount++; - } break; case 4: - if (currentVersionExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(currentVersion); - if (CHIP_NO_ERROR == TLVUnpackError) - { - currentVersionExists = true; - validArgumentCount++; - } break; case 5: - if (protocolsSupportedExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(protocolsSupported)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - protocolsSupportedExists = true; - validArgumentCount++; - } break; case 6: - if (locationExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(location); - if (CHIP_NO_ERROR == TLVUnpackError) - { - locationExists = true; - validArgumentCount++; - } break; case 7: - if (clientCanConsentExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(clientCanConsent); - if (CHIP_NO_ERROR == TLVUnpackError) - { - clientCanConsentExists = true; - validArgumentCount++; - } - break; - case 8: - if (metadataForServerExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - metadataForServer = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - metadataForServerExists = true; - validArgumentCount++; - } break; + case 8: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + metadataForServer = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6942,38 +5179,43 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 9 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOtaSoftwareUpdateServerClusterQueryImageCallback( + wasHandled = emberAfOtaSoftwareUpdateServerClusterQueryImageCallback( apCommandObj, vendorId, productId, imageType, hardwareVersion, currentVersion, protocolsSupported, const_cast(location), clientCanConsent, metadataForServer); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 9, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_OTA_SERVER_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_OTA_SERVER_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_OTA_SERVER_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OtaSoftwareUpdateServer @@ -6982,36 +5224,64 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOffCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj); break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOnCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj); break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterToggleCallback(apCommandObj); + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -7020,122 +5290,86 @@ namespace OperationalCredentials { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_OP_CERT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; chip::ByteSpan NOC; - bool NOCExists = false; chip::ByteSpan ICACertificate; - bool ICACertificateExists = false; chip::ByteSpan IPKValue; - bool IPKValueExists = false; chip::NodeId CaseAdminNode; - bool CaseAdminNodeExists = false; uint16_t AdminVendorId; - bool AdminVendorIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NOCExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NOC = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NOCExists = true; - validArgumentCount++; - } - break; - case 1: - if (ICACertificateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ICACertificate = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ICACertificateExists = true; - validArgumentCount++; - } - break; - case 2: - if (IPKValueExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - IPKValue = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - IPKValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NOC = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ICACertificate = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + IPKValue = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 3: - if (CaseAdminNodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(CaseAdminNode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - CaseAdminNodeExists = true; - validArgumentCount++; - } - break; - case 4: - if (AdminVendorIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } + break; + case 4: TLVUnpackError = aDataTlv.Get(AdminVendorId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - AdminVendorIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7145,69 +5379,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterAddOpCertCallback(apCommandObj, NOC, ICACertificate, IPKValue, CaseAdminNode, - AdminVendorId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterAddOpCertCallback(apCommandObj, NOC, ICACertificate, IPKValue, + CaseAdminNode, AdminVendorId); } break; } case ZCL_OP_CSR_REQUEST_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; chip::ByteSpan CSRNonce; - bool CSRNonceExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (CSRNonceExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - CSRNonce = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - CSRNonceExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + CSRNonce = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7217,102 +5442,70 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterOpCSRRequestCallback(apCommandObj, CSRNonce); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback(apCommandObj, CSRNonce); } break; } case ZCL_REMOVE_ALL_FABRICS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOperationalCredentialsClusterRemoveAllFabricsCallback(apCommandObj); + wasHandled = emberAfOperationalCredentialsClusterRemoveAllFabricsCallback(apCommandObj); break; } case ZCL_REMOVE_FABRIC_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::FabricId FabricId; - bool FabricIdExists = false; chip::NodeId NodeId; - bool NodeIdExists = false; uint16_t VendorId; - bool VendorIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (FabricIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(FabricId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - FabricIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(FabricId); break; case 1: - if (NodeIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(NodeId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - NodeIdExists = true; - validArgumentCount++; - } break; case 2: - if (VendorIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(VendorId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - VendorIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7322,64 +5515,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterRemoveFabricCallback(apCommandObj, FabricId, NodeId, VendorId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback(apCommandObj, FabricId, NodeId, VendorId); } break; } case ZCL_SET_FABRIC_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t VendorId; - bool VendorIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (VendorIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(VendorId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - VendorIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(VendorId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7389,65 +5574,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterSetFabricCallback(apCommandObj, VendorId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterSetFabricCallback(apCommandObj, VendorId); } break; } case ZCL_UPDATE_FABRIC_LABEL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * Label; - bool LabelExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (LabelExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - LabelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(Label); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7457,37 +5634,43 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(apCommandObj, const_cast(Label)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(apCommandObj, const_cast(Label)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OperationalCredentials @@ -7496,112 +5679,79 @@ namespace Scenes { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 4: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7611,65 +5761,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterAddSceneCallback(apCommandObj, groupId, sceneId, transitionTime, - const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterAddSceneCallback(apCommandObj, groupId, sceneId, transitionTime, + const_cast(sceneName), extensionFieldSets); } break; } case ZCL_GET_SCENE_MEMBERSHIP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7679,96 +5821,64 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, groupId); } break; } case ZCL_RECALL_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7778,64 +5888,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRecallSceneCallback(apCommandObj, groupId, sceneId, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, groupId, sceneId, transitionTime); } break; } case ZCL_REMOVE_ALL_SCENES_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7845,80 +5947,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, groupId); } break; } case ZCL_REMOVE_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -7928,80 +6010,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveSceneCallback(apCommandObj, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, groupId, sceneId); } break; } case ZCL_STORE_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -8011,80 +6073,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterStoreSceneCallback(apCommandObj, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, groupId, sceneId); } break; } case ZCL_VIEW_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -8094,36 +6136,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterViewSceneCallback(apCommandObj, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, groupId, sceneId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes @@ -8132,36 +6179,64 @@ namespace TestCluster { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_TEST_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfTestClusterClusterTestCallback(apCommandObj); + wasHandled = emberAfTestClusterClusterTestCallback(apCommandObj); break; } case ZCL_TEST_NOT_HANDLED_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfTestClusterClusterTestNotHandledCallback(apCommandObj); + wasHandled = emberAfTestClusterClusterTestNotHandledCallback(apCommandObj); break; } case ZCL_TEST_SPECIFIC_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfTestClusterClusterTestSpecificCallback(apCommandObj); + wasHandled = emberAfTestClusterClusterTestSpecificCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TEST_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TestCluster @@ -8231,8 +6306,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp index 1a3367df6a222c..a795d708d8dc4d 100644 --- a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp +++ b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp @@ -43,78 +43,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -124,119 +115,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -246,37 +194,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -285,94 +238,73 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -382,112 +314,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -497,80 +385,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -580,80 +449,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -663,128 +512,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); } break; } case ZCL_STEP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -794,97 +587,65 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, - optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, + optionOverride); } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -894,80 +655,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); } break; } case ZCL_STOP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (optionMaskExists) + 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; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -977,42 +718,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); } break; } case ZCL_STOP_WITH_ON_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -1021,82 +767,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1106,120 +842,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1229,100 +920,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1332,100 +991,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1435,64 +1062,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1502,100 +1122,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1605,100 +1192,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1708,100 +1263,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1811,121 +1333,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1935,36 +1411,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1973,36 +1455,64 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOffCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj); break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOnCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj); break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterToggleCallback(apCommandObj); + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -2033,8 +1543,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/chip-tool/gen/CHIPClientCallbacks.cpp b/examples/chip-tool/gen/CHIPClientCallbacks.cpp index 4c29e8869f75e8..635201fb7a0ab7 100644 --- a/examples/chip-tool/gen/CHIPClientCallbacks.cpp +++ b/examples/chip-tool/gen/CHIPClientCallbacks.cpp @@ -19,6 +19,8 @@ #include "gen/CHIPClientCallbacks.h" +#include + #include "gen/enums.h" #include #include @@ -80,6 +82,28 @@ using namespace ::chip; return true; \ } +#define GET_CLUSTER_RESPONSE_CALLBACKS(name) \ + Callback::Cancelable * onSuccessCallback = nullptr; \ + Callback::Cancelable * onFailureCallback = nullptr; \ + NodeId sourceIdentifier = reinterpret_cast(commandObj); \ + /* #6559: Currently, we only have one commands for the IMInvokeCommands and to a device, so the seqNum is always set to 0. */ \ + CHIP_ERROR err = gCallbacks.GetResponseCallback(sourceIdentifier, 0, &onSuccessCallback, &onFailureCallback); \ + \ + if (CHIP_NO_ERROR != err) \ + { \ + if (onSuccessCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing success callback", name); \ + } \ + \ + if (onFailureCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing failure callback", name); \ + } \ + \ + return true; \ + } + #define GET_REPORT_CALLBACK(name) \ Callback::Cancelable * onReportCallback = nullptr; \ CHIP_ERROR err = gCallbacks.GetReportCallback(sourceId, endpointId, clusterId, attributeId, &onReportCallback); \ @@ -248,6 +272,29 @@ bool emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, Em return true; } +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status) +{ + ChipLogProgress(Zcl, "DefaultResponse:"); + ChipLogProgress(Zcl, " Transaction: %p", commandObj); + LogStatus(status); + + GET_CLUSTER_RESPONSE_CALLBACKS("emberAfDefaultResponseCallback"); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onSuccessCallback); + cb->mCall(cb->mContext); + } + else + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, static_cast(status)); + } + + return true; +} + bool emberAfReadAttributesResponseCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) { ChipLogProgress(Zcl, "ReadAttributesResponse:"); @@ -891,7 +938,7 @@ bool emberAfAccountLoginClusterGetSetupPINResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "GetSetupPINResponse:"); ChipLogProgress(Zcl, " setupPIN: %s", setupPIN); - GET_RESPONSE_CALLBACKS("AccountLoginClusterGetSetupPINResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("AccountLoginClusterGetSetupPINResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -905,7 +952,7 @@ bool emberAfApplicationLauncherClusterLaunchAppResponseCallback(chip::app::Comma LogStatus(status); ChipLogProgress(Zcl, " data: %s", data); - GET_RESPONSE_CALLBACKS("ApplicationLauncherClusterLaunchAppResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ApplicationLauncherClusterLaunchAppResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -928,7 +975,7 @@ bool emberAfContentLaunchClusterLaunchContentResponseCallback(chip::app::Command ChipLogProgress(Zcl, " data: %s", data); ChipLogProgress(Zcl, " contentLaunchStatus: %" PRIu8 "", contentLaunchStatus); - GET_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchContentResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchContentResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -943,7 +990,7 @@ bool emberAfContentLaunchClusterLaunchURLResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, " data: %s", data); ChipLogProgress(Zcl, " contentLaunchStatus: %" PRIu8 "", contentLaunchStatus); - GET_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchURLResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchURLResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -956,7 +1003,7 @@ bool emberAfDoorLockClusterClearAllPinsResponseCallback(chip::app::Command * com ChipLogProgress(Zcl, "ClearAllPinsResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearAllPinsResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearAllPinsResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -977,7 +1024,7 @@ bool emberAfDoorLockClusterClearAllRfidsResponseCallback(chip::app::Command * co ChipLogProgress(Zcl, "ClearAllRfidsResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearAllRfidsResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearAllRfidsResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -998,7 +1045,7 @@ bool emberAfDoorLockClusterClearHolidayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearHolidayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1019,7 +1066,7 @@ bool emberAfDoorLockClusterClearPinResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, "ClearPinResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearPinResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1040,7 +1087,7 @@ bool emberAfDoorLockClusterClearRfidResponseCallback(chip::app::Command * comman ChipLogProgress(Zcl, "ClearRfidResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearRfidResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1061,7 +1108,7 @@ bool emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearWeekdayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1082,7 +1129,7 @@ bool emberAfDoorLockClusterClearYeardayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearYeardayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1109,7 +1156,7 @@ bool emberAfDoorLockClusterGetHolidayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " localEndTime: %" PRIu32 "", localEndTime); ChipLogProgress(Zcl, " operatingModeDuringHoliday: %" PRIu8 "", operatingModeDuringHoliday); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1138,7 +1185,7 @@ bool emberAfDoorLockClusterGetLogRecordResponseCallback(chip::app::Command * com ChipLogProgress(Zcl, " userId: %" PRIu16 "", userId); ChipLogProgress(Zcl, " pin: %s", pin); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetLogRecordResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetLogRecordResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1155,7 +1202,7 @@ bool emberAfDoorLockClusterGetPinResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); ChipLogProgress(Zcl, " pin: %s", pin); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetPinResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1172,7 +1219,7 @@ bool emberAfDoorLockClusterGetRfidResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); ChipLogProgress(Zcl, " rfid: %s", rfid); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetRfidResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1186,7 +1233,7 @@ bool emberAfDoorLockClusterGetUserTypeResponseCallback(chip::app::Command * comm ChipLogProgress(Zcl, " userId: %" PRIu16 "", userId); ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetUserTypeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetUserTypeResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1208,7 +1255,7 @@ bool emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " endHour: %" PRIu8 "", endHour); ChipLogProgress(Zcl, " endMinute: %" PRIu8 "", endMinute); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1234,7 +1281,7 @@ bool emberAfDoorLockClusterGetYeardayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " localStartTime: %" PRIu32 "", localStartTime); ChipLogProgress(Zcl, " localEndTime: %" PRIu32 "", localEndTime); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1255,7 +1302,7 @@ bool emberAfDoorLockClusterLockDoorResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, "LockDoorResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterLockDoorResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterLockDoorResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1276,7 +1323,7 @@ bool emberAfDoorLockClusterSetHolidayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetHolidayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1297,7 +1344,7 @@ bool emberAfDoorLockClusterSetPinResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, "SetPinResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetPinResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1318,7 +1365,7 @@ bool emberAfDoorLockClusterSetRfidResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, "SetRfidResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetRfidResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1339,7 +1386,7 @@ bool emberAfDoorLockClusterSetUserTypeResponseCallback(chip::app::Command * comm ChipLogProgress(Zcl, "SetUserTypeResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetUserTypeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetUserTypeResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1360,7 +1407,7 @@ bool emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetWeekdayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1381,7 +1428,7 @@ bool emberAfDoorLockClusterSetYeardayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetYeardayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1402,7 +1449,7 @@ bool emberAfDoorLockClusterUnlockDoorResponseCallback(chip::app::Command * comma ChipLogProgress(Zcl, "UnlockDoorResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterUnlockDoorResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterUnlockDoorResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1423,7 +1470,7 @@ bool emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(chip::app::Command ChipLogProgress(Zcl, "UnlockWithTimeoutResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterUnlockWithTimeoutResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterUnlockWithTimeoutResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1446,7 +1493,7 @@ bool emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(chip::app::Co ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterArmFailSafeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterArmFailSafeResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1461,7 +1508,7 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(chi ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterCommissioningCompleteResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterCommissioningCompleteResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1476,7 +1523,7 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(chip: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterSetRegulatoryConfigResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterSetRegulatoryConfigResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1490,7 +1537,7 @@ bool emberAfGroupsClusterAddGroupResponseCallback(chip::app::Command * commandOb LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("GroupsClusterAddGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterAddGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1514,7 +1561,7 @@ bool emberAfGroupsClusterGetGroupMembershipResponseCallback(chip::app::Command * ChipLogProgress(Zcl, " groupCount: %" PRIu8 "", groupCount); ChipLogProgress(Zcl, " groupList: %p", groupList); - GET_RESPONSE_CALLBACKS("GroupsClusterGetGroupMembershipResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterGetGroupMembershipResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1528,7 +1575,7 @@ bool emberAfGroupsClusterRemoveGroupResponseCallback(chip::app::Command * comman LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("GroupsClusterRemoveGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterRemoveGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1552,7 +1599,7 @@ bool emberAfGroupsClusterViewGroupResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " groupName: %s", groupName); - GET_RESPONSE_CALLBACKS("GroupsClusterViewGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterViewGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1573,7 +1620,7 @@ bool emberAfIdentifyClusterIdentifyQueryResponseCallback(chip::app::Command * co ChipLogProgress(Zcl, "IdentifyQueryResponse:"); ChipLogProgress(Zcl, " timeout: %" PRIu16 "", timeout); - GET_RESPONSE_CALLBACKS("IdentifyClusterIdentifyQueryResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("IdentifyClusterIdentifyQueryResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1586,7 +1633,7 @@ bool emberAfKeypadInputClusterSendKeyResponseCallback(chip::app::Command * comma ChipLogProgress(Zcl, "SendKeyResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("KeypadInputClusterSendKeyResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("KeypadInputClusterSendKeyResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1607,7 +1654,7 @@ bool emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(chip::app::Comm ChipLogProgress(Zcl, "MediaFastForwardResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaFastForwardResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaFastForwardResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1620,7 +1667,7 @@ bool emberAfMediaPlaybackClusterMediaNextResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, "MediaNextResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaNextResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaNextResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1633,7 +1680,7 @@ bool emberAfMediaPlaybackClusterMediaPauseResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "MediaPauseResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPauseResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPauseResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1646,7 +1693,7 @@ bool emberAfMediaPlaybackClusterMediaPlayResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, "MediaPlayResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPlayResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPlayResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1659,7 +1706,7 @@ bool emberAfMediaPlaybackClusterMediaPreviousResponseCallback(chip::app::Command ChipLogProgress(Zcl, "MediaPreviousResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPreviousResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPreviousResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1672,7 +1719,7 @@ bool emberAfMediaPlaybackClusterMediaRewindResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "MediaRewindResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaRewindResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaRewindResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1685,7 +1732,7 @@ bool emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(chip::app::Com ChipLogProgress(Zcl, "MediaSkipBackwardResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipBackwardResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipBackwardResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1698,7 +1745,7 @@ bool emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(chip::app::Comm ChipLogProgress(Zcl, "MediaSkipForwardResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipForwardResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipForwardResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1711,7 +1758,7 @@ bool emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(chip::app::Command ChipLogProgress(Zcl, "MediaSkipSeekResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipSeekResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipSeekResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1724,7 +1771,7 @@ bool emberAfMediaPlaybackClusterMediaStartOverResponseCallback(chip::app::Comman ChipLogProgress(Zcl, "MediaStartOverResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStartOverResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStartOverResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1737,7 +1784,7 @@ bool emberAfMediaPlaybackClusterMediaStopResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, "MediaStopResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStopResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStopResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1752,7 +1799,7 @@ bool emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(chip::ap ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddThreadNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddThreadNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1767,7 +1814,7 @@ bool emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(chip::app: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddWiFiNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddWiFiNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1782,7 +1829,7 @@ bool emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(chip::app: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterDisableNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterDisableNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1797,7 +1844,7 @@ bool emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(chip::app:: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterEnableNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterEnableNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1812,7 +1859,7 @@ bool emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(chip::app:: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterRemoveNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterRemoveNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1831,7 +1878,7 @@ bool emberAfNetworkCommissioningClusterScanNetworksResponseCallback( ChipLogProgress(Zcl, " wifiScanResults: %p", wifiScanResults); ChipLogProgress(Zcl, " threadScanResults: %p", threadScanResults); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterScanNetworksResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterScanNetworksResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1846,7 +1893,7 @@ bool emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(chip: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateThreadNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateThreadNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1861,7 +1908,7 @@ bool emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(chip::a ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateWiFiNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateWiFiNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1874,7 +1921,7 @@ bool emberAfOperationalCredentialsClusterSetFabricResponseCallback(chip::app::Co ChipLogProgress(Zcl, "SetFabricResponse:"); ChipLogProgress(Zcl, " FabricId: %" PRIu64 "", FabricId); - GET_RESPONSE_CALLBACKS("OperationalCredentialsClusterSetFabricResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("OperationalCredentialsClusterSetFabricResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1890,7 +1937,7 @@ bool emberAfScenesClusterAddSceneResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterAddSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterAddSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1917,7 +1964,7 @@ bool emberAfScenesClusterGetSceneMembershipResponseCallback(chip::app::Command * ChipLogProgress(Zcl, " sceneCount: %" PRIu8 "", sceneCount); ChipLogProgress(Zcl, " sceneList: %p", sceneList); - GET_RESPONSE_CALLBACKS("ScenesClusterGetSceneMembershipResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterGetSceneMembershipResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1939,7 +1986,7 @@ bool emberAfScenesClusterRemoveAllScenesResponseCallback(chip::app::Command * co LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("ScenesClusterRemoveAllScenesResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterRemoveAllScenesResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1963,7 +2010,7 @@ bool emberAfScenesClusterRemoveSceneResponseCallback(chip::app::Command * comman ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterRemoveSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterRemoveSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1987,7 +2034,7 @@ bool emberAfScenesClusterStoreSceneResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterStoreSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterStoreSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2015,7 +2062,7 @@ bool emberAfScenesClusterViewSceneResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " sceneName: %s", sceneName); ChipLogProgress(Zcl, " extensionFieldSets: %p", extensionFieldSets); - GET_RESPONSE_CALLBACKS("ScenesClusterViewSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterViewSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2039,7 +2086,7 @@ bool emberAfTvChannelClusterChangeChannelResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, " ChannelMatch: %p", ChannelMatch); ChipLogProgress(Zcl, " ErrorType: %" PRIu8 "", ErrorType); - GET_RESPONSE_CALLBACKS("TvChannelClusterChangeChannelResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("TvChannelClusterChangeChannelResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -2053,7 +2100,7 @@ bool emberAfTargetNavigatorClusterNavigateTargetResponseCallback(chip::app::Comm LogStatus(status); ChipLogProgress(Zcl, " data: %s", data); - GET_RESPONSE_CALLBACKS("TargetNavigatorClusterNavigateTargetResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("TargetNavigatorClusterNavigateTargetResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2074,7 +2121,7 @@ bool emberAfTestClusterClusterTestSpecificResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "TestSpecificResponse:"); ChipLogProgress(Zcl, " returnValue: %" PRIu8 "", returnValue); - GET_RESPONSE_CALLBACKS("TestClusterClusterTestSpecificResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("TestClusterClusterTestSpecificResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); diff --git a/examples/chip-tool/gen/CHIPClientCallbacks.h b/examples/chip-tool/gen/CHIPClientCallbacks.h index 9647b42e1c377a..0d6991d184e366 100644 --- a/examples/chip-tool/gen/CHIPClientCallbacks.h +++ b/examples/chip-tool/gen/CHIPClientCallbacks.h @@ -19,10 +19,17 @@ #pragma once +#include +#include #include #include #include +// Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus +// instead of IM status code. +// #6308 should handle IM error code on the application side, either modify this function or remove this. +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status); + // Global Response Callbacks typedef void (*DefaultSuccessCallback)(void * context); typedef void (*DefaultFailureCallback)(void * context, uint8_t status); diff --git a/examples/chip-tool/gen/CHIPClusters.cpp b/examples/chip-tool/gen/CHIPClusters.cpp index c3b051266383b9..10f574815e7b3d 100644 --- a/examples/chip-tool/gen/CHIPClusters.cpp +++ b/examples/chip-tool/gen/CHIPClusters.cpp @@ -34,10 +34,7 @@ namespace Controller { CHIP_ERROR AccountLoginCluster::GetSetupPIN(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan tempAccountIdentifier) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetSetupPINCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -52,22 +49,16 @@ CHIP_ERROR AccountLoginCluster::GetSetupPIN(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeAccountLoginClusterGetSetupPINCommand(seqNum, mEndpoint, tempAccountIdentifier); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR AccountLoginCluster::Login(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan tempAccountIdentifier, chip::ByteSpan setupPIN) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLoginCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -84,13 +75,10 @@ CHIP_ERROR AccountLoginCluster::Login(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeAccountLoginClusterLoginCommand(seqNum, mEndpoint, tempAccountIdentifier, setupPIN); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // AccountLogin Cluster Attributes @@ -186,10 +174,7 @@ CHIP_ERROR ApplicationBasicCluster::ReadAttributeClusterRevision(Callback::Cance CHIP_ERROR ApplicationLauncherCluster::LaunchApp(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan data, uint16_t catalogVendorId, chip::ByteSpan applicationId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLaunchAppCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -208,13 +193,10 @@ CHIP_ERROR ApplicationLauncherCluster::LaunchApp(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeApplicationLauncherClusterLaunchAppCommand(seqNum, mEndpoint, data, catalogVendorId, applicationId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ApplicationLauncher Cluster Attributes @@ -246,10 +228,7 @@ CHIP_ERROR ApplicationLauncherCluster::ReadAttributeClusterRevision(Callback::Ca CHIP_ERROR AudioOutputCluster::RenameOutput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index, chip::ByteSpan name) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRenameOutputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -266,21 +245,16 @@ CHIP_ERROR AudioOutputCluster::RenameOutput(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeAudioOutputClusterRenameOutputCommand(seqNum, mEndpoint, index, name); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR AudioOutputCluster::SelectOutput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSelectOutputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -295,12 +269,10 @@ CHIP_ERROR AudioOutputCluster::SelectOutput(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeAudioOutputClusterSelectOutputCommand(seqNum, mEndpoint, index); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // AudioOutput Cluster Attributes @@ -331,10 +303,7 @@ CHIP_ERROR AudioOutputCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentOpen) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBarrierControlGoToPercentCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -349,22 +318,16 @@ CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBarrierControlClusterBarrierControlGoToPercentCommand(seqNum, mEndpoint, percentOpen); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBarrierControlStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -376,12 +339,10 @@ CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBarrierControlClusterBarrierControlStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // BarrierControl Cluster Attributes @@ -435,10 +396,7 @@ CHIP_ERROR BarrierControlCluster::ReadAttributeClusterRevision(Callback::Cancela // Basic Cluster Commands CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMfgSpecificPingCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -450,12 +408,10 @@ CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBasicClusterMfgSpecificPingCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Basic Cluster Attributes @@ -630,10 +586,7 @@ CHIP_ERROR BasicCluster::ReadAttributeClusterRevision(Callback::Cancelable * onS CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -654,23 +607,17 @@ CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterBindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnbindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -691,13 +638,10 @@ CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterUnbindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Binding Cluster Attributes @@ -719,10 +663,7 @@ CHIP_ERROR BindingCluster::ReadAttributeClusterRevision(Callback::Cancelable * o CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t rateX, int16_t rateY, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -743,13 +684,10 @@ CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveColorCommand(seqNum, mEndpoint, rateX, rateY, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -757,10 +695,7 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -785,22 +720,16 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveColorTemperatureCommand( - seqNum, mEndpoint, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -821,22 +750,16 @@ CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveHueCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -857,23 +780,17 @@ CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveSaturationCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorX, uint16_t colorY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -896,23 +813,17 @@ CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorCommand( - seqNum, mEndpoint, colorX, colorY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorTemperature, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -933,23 +844,17 @@ CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorTemperatureCommand( - seqNum, mEndpoint, colorTemperature, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t direction, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -972,23 +877,17 @@ CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveToHueCommand(seqNum, mEndpoint, hue, direction, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToHueAndSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1011,23 +910,17 @@ CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToHueAndSaturationCommand( - seqNum, mEndpoint, hue, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1048,23 +941,17 @@ CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToSaturationCommand( - seqNum, mEndpoint, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t stepX, int16_t stepY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1087,13 +974,10 @@ CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStepColorCommand(seqNum, mEndpoint, stepX, stepY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -1101,10 +985,7 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu uint16_t transitionTime, uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1131,24 +1012,17 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepColorTemperatureCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, - optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1171,23 +1045,17 @@ CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepHueCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1210,22 +1078,16 @@ CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepSaturationCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopMoveStepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1242,13 +1104,10 @@ CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStopMoveStepCommand(seqNum, mEndpoint, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ColorControl Cluster Attributes @@ -1858,10 +1717,7 @@ CHIP_ERROR ColorControlCluster::ReadAttributeClusterRevision(Callback::Cancelabl CHIP_ERROR ContentLaunchCluster::LaunchContent(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t autoPlay, chip::ByteSpan data) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLaunchContentCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1878,21 +1734,16 @@ CHIP_ERROR ContentLaunchCluster::LaunchContent(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeContentLaunchClusterLaunchContentCommand(seqNum, mEndpoint, autoPlay, data); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ContentLaunchCluster::LaunchURL(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan contentURL, chip::ByteSpan displayString) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLaunchURLCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1909,13 +1760,10 @@ CHIP_ERROR ContentLaunchCluster::LaunchURL(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeContentLaunchClusterLaunchURLCommand(seqNum, mEndpoint, contentURL, displayString); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ContentLaunch Cluster Attributes @@ -2001,10 +1849,7 @@ CHIP_ERROR DescriptorCluster::ReadAttributeClusterRevision(Callback::Cancelable // DoorLock Cluster Commands CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearAllPinsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2016,20 +1861,15 @@ CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllPinsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearAllRfidsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2041,21 +1881,16 @@ CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllRfidsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2070,21 +1905,16 @@ CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2099,21 +1929,16 @@ CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2128,21 +1953,16 @@ CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2159,22 +1979,16 @@ CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2191,22 +2005,16 @@ CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2221,21 +2029,16 @@ CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t logIndex) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetLogRecordCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2250,21 +2053,16 @@ CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetLogRecordCommand(seqNum, mEndpoint, logIndex); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2279,21 +2077,16 @@ CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2308,21 +2101,16 @@ CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetUserTypeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2337,21 +2125,16 @@ CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetUserTypeCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2368,22 +2151,16 @@ CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2400,22 +2177,16 @@ CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLockDoorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2430,22 +2201,17 @@ CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterLockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint32_t localStartTime, uint32_t localEndTime, uint8_t operatingModeDuringHoliday) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2466,22 +2232,16 @@ CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetHolidayScheduleCommand( - seqNum, mEndpoint, scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2502,22 +2262,16 @@ CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetPinCommand(seqNum, mEndpoint, userId, userStatus, userType, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan id) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2538,22 +2292,16 @@ CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetRfidCommand(seqNum, mEndpoint, userId, userStatus, userType, id); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userType) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetUserTypeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2570,22 +2318,17 @@ CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetUserTypeCommand(seqNum, mEndpoint, userId, userType); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint8_t daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2612,22 +2355,16 @@ CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetWeekdayScheduleCommand( - seqNum, mEndpoint, scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint32_t localStartTime, uint32_t localEndTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2648,22 +2385,16 @@ CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId, localStartTime, localEndTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnlockDoorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2678,21 +2409,16 @@ CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterUnlockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t timeoutInSeconds, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnlockWithTimeoutCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2709,13 +2435,10 @@ CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterUnlockWithTimeoutCommand(seqNum, mEndpoint, timeoutInSeconds, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // DoorLock Cluster Attributes @@ -2777,10 +2500,7 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc Callback::Cancelable * onFailureCallback, uint16_t expiryLengthSeconds, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kArmFailSafeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2799,22 +2519,16 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGeneralCommissioningClusterArmFailSafeCommand(seqNum, mEndpoint, expiryLengthSeconds, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kCommissioningCompleteCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2826,22 +2540,17 @@ CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGeneralCommissioningClusterCommissioningCompleteCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t location, chip::ByteSpan countryCode, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetRegulatoryConfigCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2862,13 +2571,10 @@ CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGeneralCommissioningClusterSetRegulatoryConfigCommand( - seqNum, mEndpoint, location, countryCode, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // GeneralCommissioning Cluster Attributes @@ -2948,10 +2654,7 @@ CHIP_ERROR GroupKeyManagementCluster::ReadAttributeClusterRevision(Callback::Can CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2968,21 +2671,16 @@ CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterAddGroupCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddGroupIfIdentifyingCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2999,22 +2697,16 @@ CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterAddGroupIfIdentifyingCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t groupCount, uint16_t groupList) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetGroupMembershipCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3031,21 +2723,15 @@ CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterGetGroupMembershipCommand(seqNum, mEndpoint, groupCount, groupList); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllGroupsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3057,21 +2743,16 @@ CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveAllGroupsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3086,21 +2767,16 @@ CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kViewGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3115,12 +2791,10 @@ CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterViewGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Groups Cluster Attributes @@ -3150,10 +2824,7 @@ CHIP_ERROR GroupsCluster::ReadAttributeClusterRevision(Callback::Cancelable * on CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t identifyTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3168,20 +2839,15 @@ CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyCommand(seqNum, mEndpoint, identifyTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyQueryCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3193,12 +2859,10 @@ CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyQueryCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Identify Cluster Attributes @@ -3236,10 +2900,7 @@ CHIP_ERROR IdentifyCluster::ReadAttributeClusterRevision(Callback::Cancelable * CHIP_ERROR KeypadInputCluster::SendKey(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t keyCode) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSendKeyCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3254,12 +2915,10 @@ CHIP_ERROR KeypadInputCluster::SendKey(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeKeypadInputClusterSendKeyCommand(seqNum, mEndpoint, keyCode); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // KeypadInput Cluster Attributes @@ -3282,10 +2941,7 @@ CHIP_ERROR KeypadInputCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3306,22 +2962,16 @@ CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveCommand(seqNum, mEndpoint, moveMode, rate, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToLevelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3342,23 +2992,17 @@ CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelCommand(seqNum, mEndpoint, level, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToLevelWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3375,22 +3019,16 @@ CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelWithOnOffCommand(seqNum, mEndpoint, level, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3407,22 +3045,17 @@ CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterMoveWithOnOffCommand(seqNum, mEndpoint, moveMode, rate); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3445,22 +3078,16 @@ CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3479,22 +3106,16 @@ CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepWithOnOffCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3511,20 +3132,15 @@ CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopCommand(seqNum, mEndpoint, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3536,12 +3152,10 @@ CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopWithOnOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LevelControl Cluster Attributes @@ -3586,10 +3200,7 @@ CHIP_ERROR LevelControlCluster::ReadAttributeClusterRevision(Callback::Cancelabl // LowPower Cluster Commands CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSleepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3601,12 +3212,10 @@ CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLowPowerClusterSleepCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LowPower Cluster Attributes @@ -3627,10 +3236,7 @@ CHIP_ERROR LowPowerCluster::ReadAttributeClusterRevision(Callback::Cancelable * // MediaInput Cluster Commands CHIP_ERROR MediaInputCluster::HideInputStatus(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kHideInputStatusCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3642,21 +3248,16 @@ CHIP_ERROR MediaInputCluster::HideInputStatus(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterHideInputStatusCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaInputCluster::RenameInput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index, chip::ByteSpan name) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRenameInputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3673,21 +3274,16 @@ CHIP_ERROR MediaInputCluster::RenameInput(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterRenameInputCommand(seqNum, mEndpoint, index, name); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaInputCluster::SelectInput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSelectInputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3702,20 +3298,15 @@ CHIP_ERROR MediaInputCluster::SelectInput(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterSelectInputCommand(seqNum, mEndpoint, index); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaInputCluster::ShowInputStatus(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kShowInputStatusCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3727,12 +3318,10 @@ CHIP_ERROR MediaInputCluster::ShowInputStatus(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterShowInputStatusCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // MediaInput Cluster Attributes @@ -3762,10 +3351,7 @@ CHIP_ERROR MediaInputCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR MediaPlaybackCluster::MediaFastForward(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaFastForwardCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3777,20 +3363,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaFastForward(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaFastForwardCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaNext(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaNextCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3802,20 +3383,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaNext(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaNextCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaPause(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaPauseCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3827,20 +3403,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaPause(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaPauseCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaPlay(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaPlayCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3852,20 +3423,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaPlay(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaPlayCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaPrevious(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaPreviousCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3877,20 +3443,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaPrevious(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaPreviousCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaRewind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaRewindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3902,21 +3463,16 @@ CHIP_ERROR MediaPlaybackCluster::MediaRewind(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaRewindCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaSkipBackward(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint64_t deltaPositionMilliseconds) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaSkipBackwardCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3931,22 +3487,16 @@ CHIP_ERROR MediaPlaybackCluster::MediaSkipBackward(Callback::Cancelable * onSucc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeMediaPlaybackClusterMediaSkipBackwardCommand(seqNum, mEndpoint, deltaPositionMilliseconds); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaSkipForward(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint64_t deltaPositionMilliseconds) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaSkipForwardCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3961,22 +3511,16 @@ CHIP_ERROR MediaPlaybackCluster::MediaSkipForward(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeMediaPlaybackClusterMediaSkipForwardCommand(seqNum, mEndpoint, deltaPositionMilliseconds); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaSkipSeek(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint64_t position) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaSkipSeekCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3991,20 +3535,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaSkipSeek(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaSkipSeekCommand(seqNum, mEndpoint, position); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaStartOver(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaStartOverCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4016,20 +3555,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaStartOver(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaStartOverCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4041,12 +3575,10 @@ CHIP_ERROR MediaPlaybackCluster::MediaStop(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // MediaPlayback Cluster Attributes @@ -4070,10 +3602,7 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * Callback::Cancelable * onFailureCallback, chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddThreadNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4092,23 +3621,17 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddWiFiNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4129,23 +3652,17 @@ CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kDisableNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4164,23 +3681,17 @@ CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterDisableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kEnableNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4199,23 +3710,17 @@ CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterEnableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetLastNetworkCommissioningResultCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4230,23 +3735,17 @@ CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterGetLastNetworkCommissioningResultCommand(seqNum, mEndpoint, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4265,23 +3764,17 @@ CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterRemoveNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kScanNetworksCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4300,13 +3793,10 @@ CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterScanNetworksCommand(seqNum, mEndpoint, ssid, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable * onSuccessCallback, @@ -4314,10 +3804,7 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateThreadNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4336,23 +3823,17 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateWiFiNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4373,13 +3854,10 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // NetworkCommissioning Cluster Attributes @@ -4401,10 +3879,7 @@ CHIP_ERROR NetworkCommissioningCluster::ReadAttributeClusterRevision(Callback::C // OnOff Cluster Commands CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4416,20 +3891,15 @@ CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOnCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4441,20 +3911,15 @@ CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback:: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOnCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kToggleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4466,12 +3931,10 @@ CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterToggleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OnOff Cluster Attributes @@ -4514,10 +3977,7 @@ CHIP_ERROR OnOffCluster::ReadAttributeClusterRevision(Callback::Cancelable * onS CHIP_ERROR OperationalCredentialsCluster::RemoveAllFabrics(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllFabricsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4529,22 +3989,17 @@ CHIP_ERROR OperationalCredentialsCluster::RemoveAllFabrics(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterRemoveAllFabricsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::RemoveFabric(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::FabricId fabricId, chip::NodeId nodeId, uint16_t vendorId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveFabricCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4563,22 +4018,16 @@ CHIP_ERROR OperationalCredentialsCluster::RemoveFabric(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeOperationalCredentialsClusterRemoveFabricCommand(seqNum, mEndpoint, fabricId, nodeId, vendorId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::SetFabric(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t vendorId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetFabricCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4593,21 +4042,16 @@ CHIP_ERROR OperationalCredentialsCluster::SetFabric(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterSetFabricCommand(seqNum, mEndpoint, vendorId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan label) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateFabricLabelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4622,13 +4066,10 @@ CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeOperationalCredentialsClusterUpdateFabricLabelCommand(seqNum, mEndpoint, label); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OperationalCredentials Cluster Attributes @@ -4762,10 +4203,7 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, chip::ByteSpan sceneName, chip::ClusterId clusterId, uint8_t length, uint8_t value) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4792,22 +4230,16 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterAddSceneCommand( - seqNum, mEndpoint, groupId, sceneId, transitionTime, sceneName, clusterId, length, value); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetSceneMembershipCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4822,21 +4254,16 @@ CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterGetSceneMembershipCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRecallSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4855,22 +4282,16 @@ CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeScenesClusterRecallSceneCommand(seqNum, mEndpoint, groupId, sceneId, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllScenesCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4885,21 +4306,16 @@ CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveAllScenesCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4916,21 +4332,16 @@ CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStoreSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4947,21 +4358,16 @@ CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterStoreSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kViewSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4978,12 +4384,10 @@ CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterViewSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Scenes Cluster Attributes @@ -5092,10 +4496,7 @@ CHIP_ERROR SwitchCluster::ReadAttributeClusterRevision(Callback::Cancelable * on CHIP_ERROR TvChannelCluster::ChangeChannel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan match) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kChangeChannelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5110,22 +4511,17 @@ CHIP_ERROR TvChannelCluster::ChangeChannel(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTvChannelClusterChangeChannelCommand(seqNum, mEndpoint, match); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TvChannelCluster::ChangeChannelByNumber(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t majorNumber, uint16_t minorNumber) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kChangeChannelByNumberCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5142,22 +4538,16 @@ CHIP_ERROR TvChannelCluster::ChangeChannelByNumber(Callback::Cancelable * onSucc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeTvChannelClusterChangeChannelByNumberCommand(seqNum, mEndpoint, majorNumber, minorNumber); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TvChannelCluster::SkipChannel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t count) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSkipChannelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5172,12 +4562,10 @@ CHIP_ERROR TvChannelCluster::SkipChannel(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTvChannelClusterSkipChannelCommand(seqNum, mEndpoint, count); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // TvChannel Cluster Attributes @@ -5223,10 +4611,7 @@ CHIP_ERROR TvChannelCluster::ReadAttributeClusterRevision(Callback::Cancelable * CHIP_ERROR TargetNavigatorCluster::NavigateTarget(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t target, chip::ByteSpan data) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kNavigateTargetCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5243,12 +4628,10 @@ CHIP_ERROR TargetNavigatorCluster::NavigateTarget(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTargetNavigatorClusterNavigateTargetCommand(seqNum, mEndpoint, target, data); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // TargetNavigator Cluster Attributes @@ -5335,10 +4718,7 @@ CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeClusterRevision(Callback: // TestCluster Cluster Commands CHIP_ERROR TestClusterCluster::Test(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5350,20 +4730,15 @@ CHIP_ERROR TestClusterCluster::Test(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TestClusterCluster::TestNotHandled(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestNotHandledCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5375,20 +4750,15 @@ CHIP_ERROR TestClusterCluster::TestNotHandled(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestNotHandledCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TestClusterCluster::TestSpecific(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestSpecificCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5400,12 +4770,10 @@ CHIP_ERROR TestClusterCluster::TestSpecific(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestSpecificCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // TestCluster Cluster Attributes @@ -5692,10 +5060,7 @@ CHIP_ERROR TestClusterCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR ThermostatCluster::ClearWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5707,20 +5072,15 @@ CHIP_ERROR ThermostatCluster::ClearWeeklySchedule(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterClearWeeklyScheduleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::GetRelayStatusLog(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetRelayStatusLogCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5732,21 +5092,16 @@ CHIP_ERROR ThermostatCluster::GetRelayStatusLog(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterGetRelayStatusLogCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::GetWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t daysToReturn, uint8_t modeToReturn) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5763,23 +5118,17 @@ CHIP_ERROR ThermostatCluster::GetWeeklySchedule(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeThermostatClusterGetWeeklyScheduleCommand(seqNum, mEndpoint, daysToReturn, modeToReturn); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::SetWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t numberOfTransitionsForSequence, uint8_t dayOfWeekForSequence, uint8_t modeForSequence, uint8_t payload) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5800,22 +5149,16 @@ CHIP_ERROR ThermostatCluster::SetWeeklySchedule(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterSetWeeklyScheduleCommand( - seqNum, mEndpoint, numberOfTransitionsForSequence, dayOfWeekForSequence, modeForSequence, payload); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::SetpointRaiseLower(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t mode, int8_t amount) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetpointRaiseLowerCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5832,12 +5175,10 @@ CHIP_ERROR ThermostatCluster::SetpointRaiseLower(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterSetpointRaiseLowerCommand(seqNum, mEndpoint, mode, amount); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Thermostat Cluster Attributes diff --git a/examples/chip-tool/gen/IMClusterCommandHandler.cpp b/examples/chip-tool/gen/IMClusterCommandHandler.cpp index e09685cd008f94..3c6b0baa16e0a7 100644 --- a/examples/chip-tool/gen/IMClusterCommandHandler.cpp +++ b/examples/chip-tool/gen/IMClusterCommandHandler.cpp @@ -43,47 +43,62 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * setupPIN; - bool setupPINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (setupPINExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(setupPIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - setupPINExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -93,36 +108,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfAccountLoginClusterGetSetupPINResponseCallback(apCommandObj, const_cast(setupPIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfAccountLoginClusterGetSetupPINResponseCallback(apCommandObj, const_cast(setupPIN)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ACCOUNT_LOGIN_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace AccountLogin @@ -131,63 +151,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; const uint8_t * data; - bool dataExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (dataExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) - { - dataExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -197,36 +220,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfApplicationLauncherClusterLaunchAppResponseCallback(apCommandObj, status, const_cast(data)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfApplicationLauncherClusterLaunchAppResponseCallback(apCommandObj, status, const_cast(data)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_APPLICATION_LAUNCHER_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ApplicationLauncher @@ -235,63 +264,66 @@ namespace ContentLaunch { 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; const uint8_t * data; - bool dataExists = false; uint8_t contentLaunchStatus; - bool contentLaunchStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (dataExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - dataExists = true; + 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: - if (contentLaunchStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(contentLaunchStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - contentLaunchStatusExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -301,82 +333,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfContentLaunchClusterLaunchContentResponseCallback(apCommandObj, const_cast(data), - contentLaunchStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfContentLaunchClusterLaunchContentResponseCallback(apCommandObj, const_cast(data), + contentLaunchStatus); } break; } case ZCL_LAUNCH_URL_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; const uint8_t * data; - bool dataExists = false; uint8_t contentLaunchStatus; - bool contentLaunchStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (dataExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - dataExists = true; + 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: - if (contentLaunchStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(contentLaunchStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - contentLaunchStatusExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -386,37 +398,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfContentLaunchClusterLaunchURLResponseCallback(apCommandObj, const_cast(data), - contentLaunchStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfContentLaunchClusterLaunchURLResponseCallback(apCommandObj, const_cast(data), + contentLaunchStatus); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_CONTENT_LAUNCH_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ContentLaunch @@ -425,46 +442,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -474,64 +506,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -541,64 +565,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -608,64 +624,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -675,64 +683,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -742,64 +742,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -809,64 +801,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -876,128 +860,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 4: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1007,162 +935,82 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetHolidayScheduleResponseCallback(apCommandObj, scheduleId, status, localStartTime, - localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetHolidayScheduleResponseCallback( + apCommandObj, scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday); } break; } case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint16_t logEntryId; - bool logEntryIdExists = false; uint32_t timestamp; - bool timestampExists = false; uint8_t eventType; - bool eventTypeExists = false; uint8_t source; - bool sourceExists = false; uint8_t eventIdOrAlarmCode; - bool eventIdOrAlarmCodeExists = false; uint16_t userId; - bool userIdExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (logEntryIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(logEntryId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logEntryIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logEntryId); break; case 1: - if (timestampExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timestamp); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timestampExists = true; - validArgumentCount++; - } break; case 2: - if (eventTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventTypeExists = true; - validArgumentCount++; - } break; case 3: - if (sourceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(source); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sourceExists = true; - validArgumentCount++; - } break; case 4: - if (eventIdOrAlarmCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventIdOrAlarmCodeExists = true; - validArgumentCount++; - } break; case 5: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 6: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1172,114 +1020,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetLogRecordResponseCallback(apCommandObj, logEntryId, timestamp, eventType, source, - eventIdOrAlarmCode, userId, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetLogRecordResponseCallback( + apCommandObj, logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast(pin)); } break; } case ZCL_GET_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1289,114 +1093,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType, - const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType, + const_cast(pin)); } break; } case ZCL_GET_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * rfid; - bool rfidExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (rfidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(rfid); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rfidExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1406,81 +1166,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType, - const_cast(rfid)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType, + const_cast(rfid)); } break; } case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1490,176 +1230,84 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType); } break; } case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 8; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[8]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 4: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } break; case 5: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 6: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 7: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1669,129 +1317,73 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, daysMask, - startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 8, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetWeekdayScheduleResponseCallback( + apCommandObj, scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute); } break; } case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 4: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1801,65 +1393,57 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, localStartTime, - localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, + localStartTime, localEndTime); } break; } case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1869,64 +1453,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status); } break; } case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1936,64 +1512,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_SET_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2003,64 +1571,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status); } break; } case ZCL_SET_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2070,64 +1630,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status); } break; } case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2137,64 +1689,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + // 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2204,64 +1748,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2271,64 +1807,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2338,64 +1866,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status); } break; } case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2405,36 +1925,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -2443,63 +1968,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2509,82 +2037,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2594,82 +2102,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } case ZCL_SET_REGULATORY_CONFIG_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2679,37 +2167,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -2718,62 +2211,65 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2783,97 +2279,65 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t capacity; - bool capacityExists = false; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (capacityExists) + 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; } - TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - capacityExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(capacity); break; case 1: - if (groupCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupCountExists = true; - validArgumentCount++; - } break; case 2: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2883,80 +2347,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList); } break; } case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2966,97 +2410,65 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3066,36 +2478,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast(groupName)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -3104,46 +2522,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t timeout; - bool timeoutExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeout); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3153,36 +2586,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -3191,46 +2629,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3240,36 +2693,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfKeypadInputClusterSendKeyResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfKeypadInputClusterSendKeyResponseCallback(apCommandObj, status); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_KEYPAD_INPUT_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace KeypadInput @@ -3278,46 +2736,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3327,64 +2800,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_NEXT_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3394,64 +2859,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaNextResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaNextResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_PAUSE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3461,64 +2918,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaPauseResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaPauseResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_PLAY_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3528,64 +2977,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaPlayResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaPlayResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_PREVIOUS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3595,64 +3036,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaPreviousResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaPreviousResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_REWIND_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3662,64 +3095,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaRewindResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaRewindResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_SKIP_BACKWARD_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3729,64 +3154,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_SKIP_FORWARD_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3796,64 +3213,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_SKIP_SEEK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3863,64 +3272,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_START_OVER_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3930,64 +3331,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaStartOverResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaStartOverResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_STOP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3997,36 +3390,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaStopResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaStopResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_MEDIA_PLAYBACK_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace MediaPlayback @@ -4035,63 +3433,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4101,82 +3502,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4186,82 +3567,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4271,82 +3632,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4356,82 +3697,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } + // 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4441,116 +3762,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; - bool wifiScanResultsExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; - bool threadScanResultsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; case 2: - if (wifiScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(wifiScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - wifiScanResultsExists = true; - validArgumentCount++; - } break; case 3: - if (threadScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(threadScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - threadScanResultsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4560,82 +3837,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksResponseCallback( + wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback( apCommandObj, errorCode, const_cast(debugText), wifiScanResults, threadScanResults); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4645,82 +3902,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4730,37 +3967,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -4769,46 +4011,61 @@ 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_SET_FABRIC_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; chip::FabricId FabricId; - bool FabricIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (FabricIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(FabricId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - FabricIdExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4818,37 +4075,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OperationalCredentials @@ -4857,78 +4119,69 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4938,129 +4191,73 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t status; - bool statusExists = false; uint8_t capacity; - bool capacityExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneCount; - bool sceneCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * sceneList; - bool sceneListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (capacityExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) - { - capacityExists = true; - validArgumentCount++; - } break; case 2: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 3: - if (sceneCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneCountExists = true; - validArgumentCount++; - } break; case 4: - if (sceneListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(sceneList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5070,81 +4267,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId, sceneCount, - sceneList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId, + sceneCount, sceneList); } break; } case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5154,96 +4331,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5253,96 +4398,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) - { - case 0: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } - break; - case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } - break; - case 2: - if (sceneIdExists) + { + // 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; } - TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - sceneIdExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5352,146 +4465,78 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 3: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 4: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 5: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5501,37 +4546,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime, - const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime, + const_cast(sceneName), extensionFieldSets); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes @@ -5540,63 +4590,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; /* TYPE WARNING: array array defaults to */ uint8_t * ChannelMatch; - bool ChannelMatchExists = false; uint8_t ErrorType; - bool ErrorTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ChannelMatchExists) + 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; } - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(ChannelMatch)); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - ChannelMatchExists = true; + 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(ChannelMatch)); break; case 1: - if (ErrorTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(ErrorType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - ErrorTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5606,36 +4659,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTvChannelClusterChangeChannelResponseCallback(apCommandObj, ChannelMatch, ErrorType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTvChannelClusterChangeChannelResponseCallback(apCommandObj, ChannelMatch, ErrorType); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TV_CHANNEL_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TvChannel @@ -5644,63 +4702,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; const uint8_t * data; - bool dataExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (dataExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) - { - dataExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5710,36 +4771,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTargetNavigatorClusterNavigateTargetResponseCallback(apCommandObj, status, const_cast(data)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfTargetNavigatorClusterNavigateTargetResponseCallback(apCommandObj, status, const_cast(data)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TARGET_NAVIGATOR_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TargetNavigator @@ -5748,46 +4815,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t returnValue; - bool returnValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (returnValueExists) + 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; } - TLVUnpackError = aDataTlv.Get(returnValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - returnValueExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5797,36 +4879,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TEST_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TestCluster @@ -5835,95 +4922,74 @@ namespace Thermostat { 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_CURRENT_WEEKLY_SCHEDULE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t numberOfTransitionsForSequence; - bool numberOfTransitionsForSequenceExists = false; uint8_t dayOfWeekForSequence; - bool dayOfWeekForSequenceExists = false; uint8_t modeForSequence; - bool modeForSequenceExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * payload; - bool payloadExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (numberOfTransitionsForSequenceExists) + 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; } - TLVUnpackError = aDataTlv.Get(numberOfTransitionsForSequence); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - numberOfTransitionsForSequenceExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(numberOfTransitionsForSequence); break; case 1: - if (dayOfWeekForSequenceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(dayOfWeekForSequence); - if (CHIP_NO_ERROR == TLVUnpackError) - { - dayOfWeekForSequenceExists = true; - validArgumentCount++; - } break; case 2: - if (modeForSequenceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(modeForSequence); - if (CHIP_NO_ERROR == TLVUnpackError) - { - modeForSequenceExists = true; - validArgumentCount++; - } break; case 3: - if (payloadExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(payload)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - payloadExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5933,145 +4999,77 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfThermostatClusterCurrentWeeklyScheduleCallback(apCommandObj, numberOfTransitionsForSequence, - dayOfWeekForSequence, modeForSequence, payload); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfThermostatClusterCurrentWeeklyScheduleCallback(apCommandObj, numberOfTransitionsForSequence, + dayOfWeekForSequence, modeForSequence, payload); } break; } case ZCL_RELAY_STATUS_LOG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint16_t timeOfDay; - bool timeOfDayExists = false; uint16_t relayStatus; - bool relayStatusExists = false; int16_t localTemperature; - bool localTemperatureExists = false; uint8_t humidityInPercentage; - bool humidityInPercentageExists = false; int16_t setpoint; - bool setpointExists = false; uint16_t unreadEntries; - bool unreadEntriesExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeOfDayExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeOfDay); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeOfDayExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeOfDay); break; case 1: - if (relayStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(relayStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - relayStatusExists = true; - validArgumentCount++; - } break; case 2: - if (localTemperatureExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localTemperature); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localTemperatureExists = true; - validArgumentCount++; - } break; case 3: - if (humidityInPercentageExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(humidityInPercentage); - if (CHIP_NO_ERROR == TLVUnpackError) - { - humidityInPercentageExists = true; - validArgumentCount++; - } break; case 4: - if (setpointExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(setpoint); - if (CHIP_NO_ERROR == TLVUnpackError) - { - setpointExists = true; - validArgumentCount++; - } break; case 5: - if (unreadEntriesExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(unreadEntries); - if (CHIP_NO_ERROR == TLVUnpackError) - { - unreadEntriesExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6081,37 +5079,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfThermostatClusterRelayStatusLogCallback(apCommandObj, timeOfDay, relayStatus, localTemperature, - humidityInPercentage, setpoint, unreadEntries); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfThermostatClusterRelayStatusLogCallback(apCommandObj, timeOfDay, relayStatus, localTemperature, + humidityInPercentage, setpoint, unreadEntries); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_THERMOSTAT_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_THERMOSTAT_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_THERMOSTAT_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Thermostat @@ -6128,10 +5131,63 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC 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::ContentLaunch::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_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; + case ZCL_THERMOSTAT_CLUSTER_ID: + clusters::Thermostat::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp index 1a3367df6a222c..a795d708d8dc4d 100644 --- a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp @@ -43,78 +43,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -124,119 +115,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -246,37 +194,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -285,94 +238,73 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -382,112 +314,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -497,80 +385,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -580,80 +449,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -663,128 +512,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); } break; } case ZCL_STEP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -794,97 +587,65 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, - optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, + optionOverride); } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -894,80 +655,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); } break; } case ZCL_STOP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (optionMaskExists) + 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; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -977,42 +718,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); } break; } case ZCL_STOP_WITH_ON_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -1021,82 +767,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1106,120 +842,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1229,100 +920,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1332,100 +991,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1435,64 +1062,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1502,100 +1122,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1605,100 +1192,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1708,100 +1263,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1811,121 +1333,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1935,36 +1411,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1973,36 +1455,64 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOffCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj); break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOnCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj); break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterToggleCallback(apCommandObj); + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -2033,8 +1543,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp index 3b66b01ea6526b..f5d2b7ccb19650 100644 --- a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp @@ -43,78 +43,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -124,119 +115,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -246,37 +194,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -285,82 +238,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -370,120 +313,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -493,100 +391,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -596,100 +462,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -699,64 +533,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -766,100 +593,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -869,100 +663,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -972,100 +734,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1075,121 +804,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1199,36 +882,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1237,36 +926,64 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOffCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj); break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOnCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj); break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterToggleCallback(apCommandObj); + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -1294,8 +1011,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/pump-app/pump-common/gen/CHIPClientCallbacks.cpp b/examples/pump-app/pump-common/gen/CHIPClientCallbacks.cpp index 2058de4c251371..cfb4d62dc68b66 100644 --- a/examples/pump-app/pump-common/gen/CHIPClientCallbacks.cpp +++ b/examples/pump-app/pump-common/gen/CHIPClientCallbacks.cpp @@ -19,6 +19,8 @@ #include "gen/CHIPClientCallbacks.h" +#include + #include "gen/enums.h" #include #include @@ -80,6 +82,28 @@ using namespace ::chip; return true; \ } +#define GET_CLUSTER_RESPONSE_CALLBACKS(name) \ + Callback::Cancelable * onSuccessCallback = nullptr; \ + Callback::Cancelable * onFailureCallback = nullptr; \ + NodeId sourceIdentifier = reinterpret_cast(commandObj); \ + /* #6559: Currently, we only have one commands for the IMInvokeCommands and to a device, so the seqNum is always set to 0. */ \ + CHIP_ERROR err = gCallbacks.GetResponseCallback(sourceIdentifier, 0, &onSuccessCallback, &onFailureCallback); \ + \ + if (CHIP_NO_ERROR != err) \ + { \ + if (onSuccessCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing success callback", name); \ + } \ + \ + if (onFailureCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing failure callback", name); \ + } \ + \ + return true; \ + } + #define GET_REPORT_CALLBACK(name) \ Callback::Cancelable * onReportCallback = nullptr; \ CHIP_ERROR err = gCallbacks.GetReportCallback(sourceId, endpointId, clusterId, attributeId, &onReportCallback); \ @@ -248,6 +272,29 @@ bool emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, Em return true; } +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status) +{ + ChipLogProgress(Zcl, "DefaultResponse:"); + ChipLogProgress(Zcl, " Transaction: %p", commandObj); + LogStatus(status); + + GET_CLUSTER_RESPONSE_CALLBACKS("emberAfDefaultResponseCallback"); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onSuccessCallback); + cb->mCall(cb->mContext); + } + else + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, static_cast(status)); + } + + return true; +} + bool emberAfReadAttributesResponseCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) { ChipLogProgress(Zcl, "ReadAttributesResponse:"); diff --git a/examples/pump-app/pump-common/gen/CHIPClientCallbacks.h b/examples/pump-app/pump-common/gen/CHIPClientCallbacks.h index 6c1b9503135462..c0737594e5f9bc 100644 --- a/examples/pump-app/pump-common/gen/CHIPClientCallbacks.h +++ b/examples/pump-app/pump-common/gen/CHIPClientCallbacks.h @@ -19,10 +19,17 @@ #pragma once +#include +#include #include #include #include +// Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus +// instead of IM status code. +// #6308 should handle IM error code on the application side, either modify this function or remove this. +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status); + // Global Response Callbacks typedef void (*DefaultSuccessCallback)(void * context); typedef void (*DefaultFailureCallback)(void * context, uint8_t status); diff --git a/examples/pump-app/pump-common/gen/CHIPClusters.cpp b/examples/pump-app/pump-common/gen/CHIPClusters.cpp index 53b9466dfcddc9..f534b2bc3381f4 100644 --- a/examples/pump-app/pump-common/gen/CHIPClusters.cpp +++ b/examples/pump-app/pump-common/gen/CHIPClusters.cpp @@ -34,10 +34,7 @@ namespace Controller { CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t identifyTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -52,20 +49,15 @@ CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyCommand(seqNum, mEndpoint, identifyTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyQueryCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -77,12 +69,10 @@ CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyQueryCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Identify Cluster Attributes diff --git a/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp b/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp index 49001573d99ea7..8a4b1a5d0a48fb 100644 --- a/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp +++ b/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp @@ -43,78 +43,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -124,119 +115,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -246,37 +194,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -285,63 +238,66 @@ namespace Groups { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_GROUP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -351,81 +307,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterAddGroupCallback(apCommandObj, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, groupId, const_cast(groupName)); } break; } case ZCL_ADD_GROUP_IF_IDENTIFYING_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -435,81 +371,62 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterAddGroupIfIdentifyingCallback(apCommandObj, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGroupsClusterAddGroupIfIdentifyingCallback(apCommandObj, groupId, const_cast(groupName)); } break; } case ZCL_GET_GROUP_MEMBERSHIP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupCountExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupCountExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupCount); break; case 1: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -519,70 +436,62 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, groupCount, groupList); } break; } case ZCL_REMOVE_ALL_GROUPS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj); + wasHandled = emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj); break; } case ZCL_REMOVE_GROUP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -592,64 +501,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterRemoveGroupCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, groupId); } break; } case ZCL_VIEW_GROUP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -659,36 +560,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterViewGroupCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, groupId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -697,46 +603,61 @@ namespace Identify { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_IDENTIFY_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t identifyTime; - bool identifyTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (identifyTimeExists) + 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; } - TLVUnpackError = aDataTlv.Get(identifyTime); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - identifyTimeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(identifyTime); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -746,42 +667,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfIdentifyClusterIdentifyCallback(apCommandObj, identifyTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, identifyTime); } break; } case ZCL_IDENTIFY_QUERY_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj); + wasHandled = emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -790,82 +716,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -875,120 +791,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -998,100 +869,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1101,100 +940,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1204,64 +1011,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1271,100 +1071,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1374,100 +1141,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1477,100 +1212,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1580,121 +1282,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1704,36 +1360,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1742,36 +1404,64 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOffCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj); break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOnCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj); break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterToggleCallback(apCommandObj); + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -1780,112 +1470,79 @@ namespace Scenes { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 4: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1895,65 +1552,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterAddSceneCallback(apCommandObj, groupId, sceneId, transitionTime, - const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterAddSceneCallback(apCommandObj, groupId, sceneId, transitionTime, + const_cast(sceneName), extensionFieldSets); } break; } case ZCL_GET_SCENE_MEMBERSHIP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1963,96 +1612,64 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, groupId); } break; } case ZCL_RECALL_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2062,64 +1679,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRecallSceneCallback(apCommandObj, groupId, sceneId, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, groupId, sceneId, transitionTime); } break; } case ZCL_REMOVE_ALL_SCENES_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2129,80 +1738,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, groupId); } break; } case ZCL_REMOVE_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2212,80 +1801,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveSceneCallback(apCommandObj, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, groupId, sceneId); } break; } case ZCL_STORE_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2295,80 +1864,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterStoreSceneCallback(apCommandObj, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, groupId, sceneId); } break; } case ZCL_VIEW_SCENE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (groupIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2378,36 +1927,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterViewSceneCallback(apCommandObj, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, groupId, sceneId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes @@ -2444,8 +1998,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/pump-app/pump-common/gen/attribute-id.h b/examples/pump-app/pump-common/gen/attribute-id.h index e4691450f06d9c..5f295fd1d39f13 100644 --- a/examples/pump-app/pump-common/gen/attribute-id.h +++ b/examples/pump-app/pump-common/gen/attribute-id.h @@ -421,6 +421,25 @@ // Server attributes +// Attribute ids for cluster: WiFi Network Diagnostics + +// Client attributes + +// Server attributes +#define ZCL_BSSID_ATTRIBUTE_ID (0x0000) +#define ZCL_SECURITY_TYPE_ATTRIBUTE_ID (0x0001) +#define ZCL_WIFI_VERSION_ATTRIBUTE_ID (0x0002) +#define ZCL_CHANNEL_NUMBER_ATTRIBUTE_ID (0x0003) +#define ZCL_RSSI_ATTRIBUTE_ID (0x0004) +#define ZCL_BEACON_LOST_COUNT_ATTRIBUTE_ID (0x0005) +#define ZCL_BEACON_RX_COUNT_ATTRIBUTE_ID (0x0006) +#define ZCL_PACKET_MULTICAST_RX_COUNT_ATTRIBUTE_ID (0x0007) +#define ZCL_PACKET_MULTICAST_TX_COUNT_ATTRIBUTE_ID (0x0008) +#define ZCL_PACKET_UNICAST_RX_COUNT_ATTRIBUTE_ID (0x0009) +#define ZCL_PACKET_UNICAST_TX_COUNT_ATTRIBUTE_ID (0x000A) +#define ZCL_CURRENT_MAX_RATE_ATTRIBUTE_ID (0x000B) +#define ZCL_OVERRUN_COUNT_ATTRIBUTE_ID (0x000C) + // Attribute ids for cluster: Switch // Client attributes diff --git a/examples/pump-app/pump-common/gen/client-command-macro.h b/examples/pump-app/pump-common/gen/client-command-macro.h index 1ac6d9550498d1..da6eeec6b20c9f 100644 --- a/examples/pump-app/pump-common/gen/client-command-macro.h +++ b/examples/pump-app/pump-common/gen/client-command-macro.h @@ -2197,6 +2197,15 @@ \ ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID, "u", timeoutMs); +/** @brief Command description for ResetCounts + * + * Command: ResetCounts + */ +#define emberAfFillCommandWiFi \ + Network DiagnosticsClusterResetCounts() emberAfFillExternalBuffer(mask, \ + \ + ZCL_RESET_COUNTS_COMMAND_ID, "", ); + /** @brief Command description for SetFabric * * Command: SetFabric @@ -2217,6 +2226,62 @@ \ ZCL_SET_FABRIC_RESPONSE_COMMAND_ID, "u", FabricId); +/** @brief Command description for OpCSRRequest + * + * Command: OpCSRRequest + * @param CSRNonce OCTET_STRING + */ +#define emberAfFillCommandOperational \ + CredentialsClusterOpCSRRequest(CSRNonce) emberAfFillExternalBuffer(mask, \ + \ + ZCL_OP_CSR_REQUEST_COMMAND_ID, "u", CSRNonce); + +/** @brief Command description for OpCSRResponse + * + * Command: OpCSRResponse + * @param CSR OCTET_STRING + * @param CSRLen INT32U + * @param CSRNonce OCTET_STRING + * @param VendorReserved1 OCTET_STRING + * @param VendorReserved2 OCTET_STRING + * @param VendorReserved3 OCTET_STRING + * @param Signature OCTET_STRING + */ +#define emberAfFillCommandOperational \ + CredentialsClusterOpCSRResponse(CSR, CSRLen, CSRNonce, VendorReserved1, VendorReserved2, VendorReserved3, Signature) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_OP_CSR_RESPONSE_COMMAND_ID, "uuuuuuu", CSR, CSRLen, CSRNonce, VendorReserved1, \ + VendorReserved2, VendorReserved3, Signature); + +/** @brief Command description for AddOpCert + * + * Command: AddOpCert + * @param NOC OCTET_STRING + * @param ICACertificate OCTET_STRING + * @param IPKValue OCTET_STRING + * @param CaseAdminNode NODE_ID + * @param AdminVendorId INT16U + */ +#define emberAfFillCommandOperational \ + CredentialsClusterAddOpCert(NOC, ICACertificate, IPKValue, CaseAdminNode, AdminVendorId) emberAfFillExternalBuffer( \ + mask, \ + \ + ZCL_ADD_OP_CERT_COMMAND_ID, "uuuuu", NOC, ICACertificate, IPKValue, CaseAdminNode, AdminVendorId); + +/** @brief Command description for OpCertResponse + * + * Command: OpCertResponse + * @param StatusCode INT8U + * @param FabricIndex INT64U + * @param DebugText CHAR_STRING + */ +#define emberAfFillCommandOperational \ + CredentialsClusterOpCertResponse(StatusCode, FabricIndex, DebugText) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_OP_CERT_RESPONSE_COMMAND_ID, "uuu", StatusCode, FabricIndex, DebugText); + /** @brief Command description for UpdateFabricLabel * * Command: UpdateFabricLabel @@ -2240,6 +2305,15 @@ \ ZCL_REMOVE_FABRIC_COMMAND_ID, "uuu", FabricId, NodeId, VendorId); +/** @brief Command description for RemoveAllFabrics + * + * Command: RemoveAllFabrics + */ +#define emberAfFillCommandOperational \ + CredentialsClusterRemoveAllFabrics() emberAfFillExternalBuffer(mask, \ + \ + ZCL_REMOVE_ALL_FABRICS_COMMAND_ID, "", ); + /** @brief Command description for LockDoor * * Command: LockDoor diff --git a/examples/pump-app/pump-common/gen/cluster-id.h b/examples/pump-app/pump-common/gen/cluster-id.h index 7f71ea5976846c..2e57744e970149 100644 --- a/examples/pump-app/pump-common/gen/cluster-id.h +++ b/examples/pump-app/pump-common/gen/cluster-id.h @@ -98,6 +98,9 @@ // Definitions for cluster: Network Commissioning #define ZCL_NETWORK_COMMISSIONING_CLUSTER_ID (0x0031) +// Definitions for cluster: WiFi Network Diagnostics +#define ZCL_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_ID (0x0036) + // Definitions for cluster: Switch #define ZCL_SWITCH_CLUSTER_ID (0x003B) diff --git a/examples/pump-app/pump-common/gen/command-id.h b/examples/pump-app/pump-common/gen/command-id.h index cbda27333416da..82b3159d03c780 100644 --- a/examples/pump-app/pump-common/gen/command-id.h +++ b/examples/pump-app/pump-common/gen/command-id.h @@ -265,11 +265,19 @@ #define ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID (0x0F) #define ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID (0x10) +// Commands for cluster: WiFi Network Diagnostics +#define ZCL_RESET_COUNTS_COMMAND_ID (0x00) + // Commands for cluster: Operational Credentials #define ZCL_SET_FABRIC_COMMAND_ID (0x00) #define ZCL_SET_FABRIC_RESPONSE_COMMAND_ID (0x01) +#define ZCL_OP_CSR_REQUEST_COMMAND_ID (0x04) +#define ZCL_OP_CSR_RESPONSE_COMMAND_ID (0x05) +#define ZCL_ADD_OP_CERT_COMMAND_ID (0x06) +#define ZCL_OP_CERT_RESPONSE_COMMAND_ID (0x08) #define ZCL_UPDATE_FABRIC_LABEL_COMMAND_ID (0x09) #define ZCL_REMOVE_FABRIC_COMMAND_ID (0x0A) +#define ZCL_REMOVE_ALL_FABRICS_COMMAND_ID (0x0B) // Commands for cluster: Door Lock #define ZCL_LOCK_DOOR_COMMAND_ID (0x00) diff --git a/examples/pump-app/pump-common/gen/enums.h b/examples/pump-app/pump-common/gen/enums.h index c14422f16eb01d..0bc06eb7476011 100644 --- a/examples/pump-app/pump-common/gen/enums.h +++ b/examples/pump-app/pump-common/gen/enums.h @@ -2527,6 +2527,17 @@ typedef enum EMBER_ZCL_SATURATION_STEP_MODE_DOWN = 3, } EmberAfSaturationStepMode; +// Enum for SecurityType +typedef enum +{ + EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED = 0, + EMBER_ZCL_SECURITY_TYPE_NONE = 1, + EMBER_ZCL_SECURITY_TYPE_WEP = 2, + EMBER_ZCL_SECURITY_TYPE_WPA = 3, + EMBER_ZCL_SECURITY_TYPE_WPA2 = 4, + EMBER_ZCL_SECURITY_TYPE_WPA3 = 5, +} EmberAfSecurityType; + // Enum for SensingLightSensorType typedef enum { @@ -2825,6 +2836,17 @@ typedef enum EMBER_ZCL_WARNING_STOBE_USE_STROBE = 1, } EmberAfWarningStobe; +// Enum for WiFiVersionType +typedef enum +{ + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11A = 0, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11B = 1, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11G = 2, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11N = 3, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11AC = 4, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11AX = 5, +} EmberAfWiFiVersionType; + // Enum for WwahIasZoneEnrollmentMode typedef enum { diff --git a/examples/pump-app/pump-common/gen/print-cluster.h b/examples/pump-app/pump-common/gen/print-cluster.h index 886dad371554b7..73bedd002b5aa4 100644 --- a/examples/pump-app/pump-common/gen/print-cluster.h +++ b/examples/pump-app/pump-common/gen/print-cluster.h @@ -180,6 +180,13 @@ #define CHIP_PRINTCLUSTER_NETWORK_COMMISSIONING_CLUSTER #endif +#if defined(ZCL_USING_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_SERVER) || defined(ZCL_USING_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_WIFI_NETWORK_DIAGNOSTICS_CLUSTER \ + { ZCL_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_ID, 54, "WiFi Network Diagnostics" }, +#else +#define CHIP_PRINTCLUSTER_WIFI_NETWORK_DIAGNOSTICS_CLUSTER +#endif + #if defined(ZCL_USING_SWITCH_CLUSTER_SERVER) || defined(ZCL_USING_SWITCH_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_SWITCH_CLUSTER { ZCL_SWITCH_CLUSTER_ID, 59, "Switch" }, #else @@ -906,6 +913,7 @@ CHIP_PRINTCLUSTER_OTA_CLIENT_CLUSTER \ CHIP_PRINTCLUSTER_GENERAL_COMMISSIONING_CLUSTER \ CHIP_PRINTCLUSTER_NETWORK_COMMISSIONING_CLUSTER \ + CHIP_PRINTCLUSTER_WIFI_NETWORK_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_SWITCH_CLUSTER \ CHIP_PRINTCLUSTER_OPERATIONAL_CREDENTIALS_CLUSTER \ CHIP_PRINTCLUSTER_SHADE_CONFIG_CLUSTER \ diff --git a/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.cpp b/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.cpp index 2058de4c251371..cfb4d62dc68b66 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.cpp @@ -19,6 +19,8 @@ #include "gen/CHIPClientCallbacks.h" +#include + #include "gen/enums.h" #include #include @@ -80,6 +82,28 @@ using namespace ::chip; return true; \ } +#define GET_CLUSTER_RESPONSE_CALLBACKS(name) \ + Callback::Cancelable * onSuccessCallback = nullptr; \ + Callback::Cancelable * onFailureCallback = nullptr; \ + NodeId sourceIdentifier = reinterpret_cast(commandObj); \ + /* #6559: Currently, we only have one commands for the IMInvokeCommands and to a device, so the seqNum is always set to 0. */ \ + CHIP_ERROR err = gCallbacks.GetResponseCallback(sourceIdentifier, 0, &onSuccessCallback, &onFailureCallback); \ + \ + if (CHIP_NO_ERROR != err) \ + { \ + if (onSuccessCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing success callback", name); \ + } \ + \ + if (onFailureCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing failure callback", name); \ + } \ + \ + return true; \ + } + #define GET_REPORT_CALLBACK(name) \ Callback::Cancelable * onReportCallback = nullptr; \ CHIP_ERROR err = gCallbacks.GetReportCallback(sourceId, endpointId, clusterId, attributeId, &onReportCallback); \ @@ -248,6 +272,29 @@ bool emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, Em return true; } +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status) +{ + ChipLogProgress(Zcl, "DefaultResponse:"); + ChipLogProgress(Zcl, " Transaction: %p", commandObj); + LogStatus(status); + + GET_CLUSTER_RESPONSE_CALLBACKS("emberAfDefaultResponseCallback"); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onSuccessCallback); + cb->mCall(cb->mContext); + } + else + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, static_cast(status)); + } + + return true; +} + bool emberAfReadAttributesResponseCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) { ChipLogProgress(Zcl, "ReadAttributesResponse:"); diff --git a/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.h b/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.h index 6c1b9503135462..c0737594e5f9bc 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.h +++ b/examples/pump-controller-app/pump-controller-common/gen/CHIPClientCallbacks.h @@ -19,10 +19,17 @@ #pragma once +#include +#include #include #include #include +// Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus +// instead of IM status code. +// #6308 should handle IM error code on the application side, either modify this function or remove this. +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status); + // Global Response Callbacks typedef void (*DefaultSuccessCallback)(void * context); typedef void (*DefaultFailureCallback)(void * context, uint8_t status); diff --git a/examples/pump-controller-app/pump-controller-common/gen/CHIPClusters.cpp b/examples/pump-controller-app/pump-controller-common/gen/CHIPClusters.cpp index 6eb62e071e7856..78f4a7c66d544f 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/CHIPClusters.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/CHIPClusters.cpp @@ -33,10 +33,7 @@ namespace Controller { // OnOff Cluster Commands CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -48,20 +45,15 @@ CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOnCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -73,20 +65,15 @@ CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback:: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOnCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kToggleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -98,12 +85,10 @@ CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterToggleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OnOff Cluster Attributes diff --git a/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp b/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp index 6382ba65a992e5..000d00b322d03b 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp @@ -43,78 +43,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -124,119 +115,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -246,37 +194,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -285,82 +238,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -370,120 +313,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -493,100 +391,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -596,100 +462,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -699,64 +533,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -766,100 +593,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -869,100 +663,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -972,100 +734,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1075,121 +804,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1199,36 +882,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1253,8 +942,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/pump-controller-app/pump-controller-common/gen/attribute-id.h b/examples/pump-controller-app/pump-controller-common/gen/attribute-id.h index e4691450f06d9c..5f295fd1d39f13 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/attribute-id.h +++ b/examples/pump-controller-app/pump-controller-common/gen/attribute-id.h @@ -421,6 +421,25 @@ // Server attributes +// Attribute ids for cluster: WiFi Network Diagnostics + +// Client attributes + +// Server attributes +#define ZCL_BSSID_ATTRIBUTE_ID (0x0000) +#define ZCL_SECURITY_TYPE_ATTRIBUTE_ID (0x0001) +#define ZCL_WIFI_VERSION_ATTRIBUTE_ID (0x0002) +#define ZCL_CHANNEL_NUMBER_ATTRIBUTE_ID (0x0003) +#define ZCL_RSSI_ATTRIBUTE_ID (0x0004) +#define ZCL_BEACON_LOST_COUNT_ATTRIBUTE_ID (0x0005) +#define ZCL_BEACON_RX_COUNT_ATTRIBUTE_ID (0x0006) +#define ZCL_PACKET_MULTICAST_RX_COUNT_ATTRIBUTE_ID (0x0007) +#define ZCL_PACKET_MULTICAST_TX_COUNT_ATTRIBUTE_ID (0x0008) +#define ZCL_PACKET_UNICAST_RX_COUNT_ATTRIBUTE_ID (0x0009) +#define ZCL_PACKET_UNICAST_TX_COUNT_ATTRIBUTE_ID (0x000A) +#define ZCL_CURRENT_MAX_RATE_ATTRIBUTE_ID (0x000B) +#define ZCL_OVERRUN_COUNT_ATTRIBUTE_ID (0x000C) + // Attribute ids for cluster: Switch // Client attributes diff --git a/examples/pump-controller-app/pump-controller-common/gen/client-command-macro.h b/examples/pump-controller-app/pump-controller-common/gen/client-command-macro.h index 1ac6d9550498d1..da6eeec6b20c9f 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/client-command-macro.h +++ b/examples/pump-controller-app/pump-controller-common/gen/client-command-macro.h @@ -2197,6 +2197,15 @@ \ ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID, "u", timeoutMs); +/** @brief Command description for ResetCounts + * + * Command: ResetCounts + */ +#define emberAfFillCommandWiFi \ + Network DiagnosticsClusterResetCounts() emberAfFillExternalBuffer(mask, \ + \ + ZCL_RESET_COUNTS_COMMAND_ID, "", ); + /** @brief Command description for SetFabric * * Command: SetFabric @@ -2217,6 +2226,62 @@ \ ZCL_SET_FABRIC_RESPONSE_COMMAND_ID, "u", FabricId); +/** @brief Command description for OpCSRRequest + * + * Command: OpCSRRequest + * @param CSRNonce OCTET_STRING + */ +#define emberAfFillCommandOperational \ + CredentialsClusterOpCSRRequest(CSRNonce) emberAfFillExternalBuffer(mask, \ + \ + ZCL_OP_CSR_REQUEST_COMMAND_ID, "u", CSRNonce); + +/** @brief Command description for OpCSRResponse + * + * Command: OpCSRResponse + * @param CSR OCTET_STRING + * @param CSRLen INT32U + * @param CSRNonce OCTET_STRING + * @param VendorReserved1 OCTET_STRING + * @param VendorReserved2 OCTET_STRING + * @param VendorReserved3 OCTET_STRING + * @param Signature OCTET_STRING + */ +#define emberAfFillCommandOperational \ + CredentialsClusterOpCSRResponse(CSR, CSRLen, CSRNonce, VendorReserved1, VendorReserved2, VendorReserved3, Signature) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_OP_CSR_RESPONSE_COMMAND_ID, "uuuuuuu", CSR, CSRLen, CSRNonce, VendorReserved1, \ + VendorReserved2, VendorReserved3, Signature); + +/** @brief Command description for AddOpCert + * + * Command: AddOpCert + * @param NOC OCTET_STRING + * @param ICACertificate OCTET_STRING + * @param IPKValue OCTET_STRING + * @param CaseAdminNode NODE_ID + * @param AdminVendorId INT16U + */ +#define emberAfFillCommandOperational \ + CredentialsClusterAddOpCert(NOC, ICACertificate, IPKValue, CaseAdminNode, AdminVendorId) emberAfFillExternalBuffer( \ + mask, \ + \ + ZCL_ADD_OP_CERT_COMMAND_ID, "uuuuu", NOC, ICACertificate, IPKValue, CaseAdminNode, AdminVendorId); + +/** @brief Command description for OpCertResponse + * + * Command: OpCertResponse + * @param StatusCode INT8U + * @param FabricIndex INT64U + * @param DebugText CHAR_STRING + */ +#define emberAfFillCommandOperational \ + CredentialsClusterOpCertResponse(StatusCode, FabricIndex, DebugText) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_OP_CERT_RESPONSE_COMMAND_ID, "uuu", StatusCode, FabricIndex, DebugText); + /** @brief Command description for UpdateFabricLabel * * Command: UpdateFabricLabel @@ -2240,6 +2305,15 @@ \ ZCL_REMOVE_FABRIC_COMMAND_ID, "uuu", FabricId, NodeId, VendorId); +/** @brief Command description for RemoveAllFabrics + * + * Command: RemoveAllFabrics + */ +#define emberAfFillCommandOperational \ + CredentialsClusterRemoveAllFabrics() emberAfFillExternalBuffer(mask, \ + \ + ZCL_REMOVE_ALL_FABRICS_COMMAND_ID, "", ); + /** @brief Command description for LockDoor * * Command: LockDoor diff --git a/examples/pump-controller-app/pump-controller-common/gen/cluster-id.h b/examples/pump-controller-app/pump-controller-common/gen/cluster-id.h index 7f71ea5976846c..2e57744e970149 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/cluster-id.h +++ b/examples/pump-controller-app/pump-controller-common/gen/cluster-id.h @@ -98,6 +98,9 @@ // Definitions for cluster: Network Commissioning #define ZCL_NETWORK_COMMISSIONING_CLUSTER_ID (0x0031) +// Definitions for cluster: WiFi Network Diagnostics +#define ZCL_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_ID (0x0036) + // Definitions for cluster: Switch #define ZCL_SWITCH_CLUSTER_ID (0x003B) diff --git a/examples/pump-controller-app/pump-controller-common/gen/command-id.h b/examples/pump-controller-app/pump-controller-common/gen/command-id.h index cbda27333416da..82b3159d03c780 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/command-id.h +++ b/examples/pump-controller-app/pump-controller-common/gen/command-id.h @@ -265,11 +265,19 @@ #define ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID (0x0F) #define ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID (0x10) +// Commands for cluster: WiFi Network Diagnostics +#define ZCL_RESET_COUNTS_COMMAND_ID (0x00) + // Commands for cluster: Operational Credentials #define ZCL_SET_FABRIC_COMMAND_ID (0x00) #define ZCL_SET_FABRIC_RESPONSE_COMMAND_ID (0x01) +#define ZCL_OP_CSR_REQUEST_COMMAND_ID (0x04) +#define ZCL_OP_CSR_RESPONSE_COMMAND_ID (0x05) +#define ZCL_ADD_OP_CERT_COMMAND_ID (0x06) +#define ZCL_OP_CERT_RESPONSE_COMMAND_ID (0x08) #define ZCL_UPDATE_FABRIC_LABEL_COMMAND_ID (0x09) #define ZCL_REMOVE_FABRIC_COMMAND_ID (0x0A) +#define ZCL_REMOVE_ALL_FABRICS_COMMAND_ID (0x0B) // Commands for cluster: Door Lock #define ZCL_LOCK_DOOR_COMMAND_ID (0x00) diff --git a/examples/pump-controller-app/pump-controller-common/gen/enums.h b/examples/pump-controller-app/pump-controller-common/gen/enums.h index c14422f16eb01d..0bc06eb7476011 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/enums.h +++ b/examples/pump-controller-app/pump-controller-common/gen/enums.h @@ -2527,6 +2527,17 @@ typedef enum EMBER_ZCL_SATURATION_STEP_MODE_DOWN = 3, } EmberAfSaturationStepMode; +// Enum for SecurityType +typedef enum +{ + EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED = 0, + EMBER_ZCL_SECURITY_TYPE_NONE = 1, + EMBER_ZCL_SECURITY_TYPE_WEP = 2, + EMBER_ZCL_SECURITY_TYPE_WPA = 3, + EMBER_ZCL_SECURITY_TYPE_WPA2 = 4, + EMBER_ZCL_SECURITY_TYPE_WPA3 = 5, +} EmberAfSecurityType; + // Enum for SensingLightSensorType typedef enum { @@ -2825,6 +2836,17 @@ typedef enum EMBER_ZCL_WARNING_STOBE_USE_STROBE = 1, } EmberAfWarningStobe; +// Enum for WiFiVersionType +typedef enum +{ + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11A = 0, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11B = 1, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11G = 2, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11N = 3, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11AC = 4, + EMBER_ZCL_WI_FI_VERSION_TYPE_802__11AX = 5, +} EmberAfWiFiVersionType; + // Enum for WwahIasZoneEnrollmentMode typedef enum { diff --git a/examples/pump-controller-app/pump-controller-common/gen/print-cluster.h b/examples/pump-controller-app/pump-controller-common/gen/print-cluster.h index 886dad371554b7..73bedd002b5aa4 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/print-cluster.h +++ b/examples/pump-controller-app/pump-controller-common/gen/print-cluster.h @@ -180,6 +180,13 @@ #define CHIP_PRINTCLUSTER_NETWORK_COMMISSIONING_CLUSTER #endif +#if defined(ZCL_USING_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_SERVER) || defined(ZCL_USING_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_WIFI_NETWORK_DIAGNOSTICS_CLUSTER \ + { ZCL_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_ID, 54, "WiFi Network Diagnostics" }, +#else +#define CHIP_PRINTCLUSTER_WIFI_NETWORK_DIAGNOSTICS_CLUSTER +#endif + #if defined(ZCL_USING_SWITCH_CLUSTER_SERVER) || defined(ZCL_USING_SWITCH_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_SWITCH_CLUSTER { ZCL_SWITCH_CLUSTER_ID, 59, "Switch" }, #else @@ -906,6 +913,7 @@ CHIP_PRINTCLUSTER_OTA_CLIENT_CLUSTER \ CHIP_PRINTCLUSTER_GENERAL_COMMISSIONING_CLUSTER \ CHIP_PRINTCLUSTER_NETWORK_COMMISSIONING_CLUSTER \ + CHIP_PRINTCLUSTER_WIFI_NETWORK_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_SWITCH_CLUSTER \ CHIP_PRINTCLUSTER_OPERATIONAL_CREDENTIALS_CLUSTER \ CHIP_PRINTCLUSTER_SHADE_CONFIG_CLUSTER \ diff --git a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp index 6382ba65a992e5..000d00b322d03b 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp @@ -43,78 +43,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -124,119 +115,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -246,37 +194,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -285,82 +238,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -370,120 +313,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -493,100 +391,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -596,100 +462,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -699,64 +533,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -766,100 +593,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -869,100 +663,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -972,100 +734,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1075,121 +804,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1199,36 +882,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1253,8 +942,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp index 4da2336552ff55..74754a044ea9d5 100644 --- a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp +++ b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp @@ -43,47 +43,62 @@ namespace AccountLogin { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_GET_SETUP_PIN_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * tempAccountIdentifier; - bool tempAccountIdentifierExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (tempAccountIdentifierExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(tempAccountIdentifier); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - tempAccountIdentifierExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(tempAccountIdentifier); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -93,82 +108,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfAccountLoginClusterGetSetupPINCallback(apCommandObj, const_cast(tempAccountIdentifier)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfAccountLoginClusterGetSetupPINCallback(apCommandObj, const_cast(tempAccountIdentifier)); } break; } case ZCL_LOGIN_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; const uint8_t * tempAccountIdentifier; - bool tempAccountIdentifierExists = false; const uint8_t * setupPIN; - bool setupPINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (tempAccountIdentifierExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(tempAccountIdentifier); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - tempAccountIdentifierExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(tempAccountIdentifier); break; case 1: - if (setupPINExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(setupPIN); - if (CHIP_NO_ERROR == TLVUnpackError) - { - setupPINExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -178,37 +174,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfAccountLoginClusterLoginCallback(apCommandObj, const_cast(tempAccountIdentifier), - const_cast(setupPIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfAccountLoginClusterLoginCallback(apCommandObj, const_cast(tempAccountIdentifier), + const_cast(setupPIN)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ACCOUNT_LOGIN_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace AccountLogin @@ -217,64 +218,67 @@ namespace ApplicationLauncher { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_LAUNCH_APP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; const uint8_t * data; - bool dataExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * application; - bool applicationExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (dataExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - dataExists = true; + 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: - if (applicationExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(application)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - applicationExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -284,36 +288,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfApplicationLauncherClusterLaunchAppCallback(apCommandObj, const_cast(data), application); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfApplicationLauncherClusterLaunchAppCallback(apCommandObj, const_cast(data), application); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_APPLICATION_LAUNCHER_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ApplicationLauncher @@ -322,63 +332,66 @@ namespace AudioOutput { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_RENAME_OUTPUT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t index; - bool indexExists = false; const uint8_t * name; - bool nameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (indexExists) + 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; } - TLVUnpackError = aDataTlv.Get(index); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - indexExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(index); break; case 1: - if (nameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(name); - if (CHIP_NO_ERROR == TLVUnpackError) - { - nameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -388,64 +401,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfAudioOutputClusterRenameOutputCallback(apCommandObj, index, const_cast(name)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfAudioOutputClusterRenameOutputCallback(apCommandObj, index, const_cast(name)); } break; } case ZCL_SELECT_OUTPUT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t index; - bool indexExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (indexExists) + 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; } - TLVUnpackError = aDataTlv.Get(index); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - indexExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(index); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -455,36 +460,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfAudioOutputClusterSelectOutputCallback(apCommandObj, index); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfAudioOutputClusterSelectOutputCallback(apCommandObj, index); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_AUDIO_OUTPUT_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_AUDIO_OUTPUT_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_AUDIO_OUTPUT_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace AudioOutput @@ -493,63 +503,66 @@ namespace ContentLaunch { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_LAUNCH_CONTENT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t autoPlay; - bool autoPlayExists = false; const uint8_t * data; - bool dataExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (autoPlayExists) + 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; } - TLVUnpackError = aDataTlv.Get(autoPlay); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - autoPlayExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(autoPlay); break; case 1: - if (dataExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) - { - dataExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -559,82 +572,62 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfContentLaunchClusterLaunchContentCallback(apCommandObj, autoPlay, const_cast(data)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfContentLaunchClusterLaunchContentCallback(apCommandObj, autoPlay, const_cast(data)); } break; } case ZCL_LAUNCH_URL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; const uint8_t * contentURL; - bool contentURLExists = false; const uint8_t * displayString; - bool displayStringExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (contentURLExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(contentURL); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - contentURLExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(contentURL); break; case 1: - if (displayStringExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(displayString); - if (CHIP_NO_ERROR == TLVUnpackError) - { - displayStringExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -644,37 +637,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfContentLaunchClusterLaunchURLCallback(apCommandObj, const_cast(contentURL), - const_cast(displayString)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfContentLaunchClusterLaunchURLCallback(apCommandObj, const_cast(contentURL), + const_cast(displayString)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_CONTENT_LAUNCH_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ContentLaunch @@ -683,78 +681,69 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (expiryLengthSecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -764,119 +753,76 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs); } break; } case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj); break; } case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t location; - bool locationExists = false; const uint8_t * countryCode; - bool countryCodeExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (locationExists) + 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; } - TLVUnpackError = aDataTlv.Get(location); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - locationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(location); break; case 1: - if (countryCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - countryCodeExists = true; - validArgumentCount++; - } break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -886,37 +832,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( apCommandObj, location, const_cast(countryCode), breadcrumb, timeoutMs); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -925,46 +876,61 @@ namespace KeypadInput { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_SEND_KEY_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t keyCode; - bool keyCodeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (keyCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(keyCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - keyCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(keyCode); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -974,36 +940,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfKeypadInputClusterSendKeyCallback(apCommandObj, keyCode); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfKeypadInputClusterSendKeyCallback(apCommandObj, keyCode); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_KEYPAD_INPUT_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace KeypadInput @@ -1012,94 +983,73 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1109,112 +1059,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1224,80 +1130,61 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride); } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (levelExists) + 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; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1307,80 +1194,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime); } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (moveModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1390,128 +1257,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate); } break; } case ZCL_STEP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) - { - case 0: - if (stepModeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepModeExists = true; - validArgumentCount++; - } - break; - case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } - break; - case 2: - if (transitionTimeExists) + // 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; } - TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - transitionTimeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); + break; + case 1: + TLVUnpackError = aDataTlv.Get(stepSize); + break; + case 2: + TLVUnpackError = aDataTlv.Get(transitionTime); break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1521,97 +1332,65 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, - optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask, + optionOverride); } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (stepModeExists) + 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; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1621,80 +1400,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime); } break; } case ZCL_STOP_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (optionMaskExists) + 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; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1704,42 +1463,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride); } break; } case ZCL_STOP_WITH_ON_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -1748,24 +1512,52 @@ namespace LowPower { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_SLEEP_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfLowPowerClusterSleepCallback(apCommandObj); + wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LOW_POWER_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LOW_POWER_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_LOW_POWER_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LowPower @@ -1774,69 +1566,72 @@ namespace MediaInput { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_HIDE_INPUT_STATUS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaInputClusterHideInputStatusCallback(apCommandObj); + wasHandled = emberAfMediaInputClusterHideInputStatusCallback(apCommandObj); break; } case ZCL_RENAME_INPUT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t index; - bool indexExists = false; const uint8_t * name; - bool nameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (indexExists) + 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; } - TLVUnpackError = aDataTlv.Get(index); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - indexExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(index); break; case 1: - if (nameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(name); - if (CHIP_NO_ERROR == TLVUnpackError) - { - nameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1846,64 +1641,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaInputClusterRenameInputCallback(apCommandObj, index, const_cast(name)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaInputClusterRenameInputCallback(apCommandObj, index, const_cast(name)); } break; } case ZCL_SELECT_INPUT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t index; - bool indexExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (indexExists) + 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; } - TLVUnpackError = aDataTlv.Get(index); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - indexExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(index); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1913,42 +1700,47 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaInputClusterSelectInputCallback(apCommandObj, index); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaInputClusterSelectInputCallback(apCommandObj, index); } break; } case ZCL_SHOW_INPUT_STATUS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaInputClusterShowInputStatusCallback(apCommandObj); + wasHandled = emberAfMediaInputClusterShowInputStatusCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_MEDIA_INPUT_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_MEDIA_INPUT_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_MEDIA_INPUT_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace MediaInput @@ -1957,82 +1749,97 @@ namespace MediaPlayback { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_MEDIA_FAST_FORWARD_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaFastForwardCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaFastForwardCallback(apCommandObj); break; } case ZCL_MEDIA_NEXT_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaNextCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaNextCallback(apCommandObj); break; } case ZCL_MEDIA_PAUSE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaPauseCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaPauseCallback(apCommandObj); break; } case ZCL_MEDIA_PLAY_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaPlayCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaPlayCallback(apCommandObj); break; } case ZCL_MEDIA_PREVIOUS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaPreviousCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaPreviousCallback(apCommandObj); break; } case ZCL_MEDIA_REWIND_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaRewindCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaRewindCallback(apCommandObj); break; } case ZCL_MEDIA_SKIP_BACKWARD_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint64_t deltaPositionMilliseconds; - bool deltaPositionMillisecondsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (deltaPositionMillisecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(deltaPositionMilliseconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - deltaPositionMillisecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(deltaPositionMilliseconds); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2042,64 +1849,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipBackwardCallback(apCommandObj, deltaPositionMilliseconds); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardCallback(apCommandObj, deltaPositionMilliseconds); } break; } case ZCL_MEDIA_SKIP_FORWARD_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint64_t deltaPositionMilliseconds; - bool deltaPositionMillisecondsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (deltaPositionMillisecondsExists) + 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; } - TLVUnpackError = aDataTlv.Get(deltaPositionMilliseconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - deltaPositionMillisecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(deltaPositionMilliseconds); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2109,64 +1908,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipForwardCallback(apCommandObj, deltaPositionMilliseconds); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardCallback(apCommandObj, deltaPositionMilliseconds); } break; } case ZCL_MEDIA_SKIP_SEEK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint64_t position; - bool positionExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (positionExists) + 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; } - TLVUnpackError = aDataTlv.Get(position); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - positionExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(position); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2176,48 +1967,53 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipSeekCallback(apCommandObj, position); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipSeekCallback(apCommandObj, position); } break; } case ZCL_MEDIA_START_OVER_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaStartOverCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaStartOverCallback(apCommandObj); break; } case ZCL_MEDIA_STOP_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfMediaPlaybackClusterMediaStopCallback(apCommandObj); + wasHandled = emberAfMediaPlaybackClusterMediaStopCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_MEDIA_PLAYBACK_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace MediaPlayback @@ -2226,36 +2022,64 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_OFF_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOffCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj); break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterOnCallback(apCommandObj); + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj); break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfOnOffClusterToggleCallback(apCommandObj); + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_ON_OFF_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -2264,47 +2088,62 @@ namespace TvChannel { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_CHANGE_CHANNEL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * match; - bool matchExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (matchExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(match); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - matchExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(match); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2314,80 +2153,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTvChannelClusterChangeChannelCallback(apCommandObj, const_cast(match)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTvChannelClusterChangeChannelCallback(apCommandObj, const_cast(match)); } break; } case ZCL_CHANGE_CHANNEL_BY_NUMBER_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t majorNumber; - bool majorNumberExists = false; uint16_t minorNumber; - bool minorNumberExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (majorNumberExists) + 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; } - TLVUnpackError = aDataTlv.Get(majorNumber); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - majorNumberExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(majorNumber); break; case 1: - if (minorNumberExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(minorNumber); - if (CHIP_NO_ERROR == TLVUnpackError) - { - minorNumberExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2397,64 +2216,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTvChannelClusterChangeChannelByNumberCallback(apCommandObj, majorNumber, minorNumber); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTvChannelClusterChangeChannelByNumberCallback(apCommandObj, majorNumber, minorNumber); } break; } case ZCL_SKIP_CHANNEL_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t Count; - bool CountExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (CountExists) + 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; } - TLVUnpackError = aDataTlv.Get(Count); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - CountExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(Count); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2464,36 +2275,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTvChannelClusterSkipChannelCallback(apCommandObj, Count); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTvChannelClusterSkipChannelCallback(apCommandObj, Count); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TV_CHANNEL_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TvChannel @@ -2502,63 +2318,66 @@ namespace TargetNavigator { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_NAVIGATE_TARGET_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t target; - bool targetExists = false; const uint8_t * data; - bool dataExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (targetExists) + 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; } - TLVUnpackError = aDataTlv.Get(target); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - targetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(target); break; case 1: - if (dataExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) - { - dataExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2568,36 +2387,41 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTargetNavigatorClusterNavigateTargetCallback(apCommandObj, target, const_cast(data)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTargetNavigatorClusterNavigateTargetCallback(apCommandObj, target, const_cast(data)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TARGET_NAVIGATOR_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TargetNavigator @@ -2655,8 +2479,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/examples/window-app/common/gen/IMClusterCommandHandler.cpp b/examples/window-app/common/gen/IMClusterCommandHandler.cpp index a1dfbb84b5cfd6..3a388a48e8599c 100644 --- a/examples/window-app/common/gen/IMClusterCommandHandler.cpp +++ b/examples/window-app/common/gen/IMClusterCommandHandler.cpp @@ -43,82 +43,72 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -128,120 +118,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -251,100 +196,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, + timeoutMs); } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -354,100 +267,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (networkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -457,64 +338,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs); } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutMsExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -524,100 +398,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs); } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (NetworkIDExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -627,100 +468,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs); } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -730,100 +539,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (operationalDatasetExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -833,121 +609,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, breadcrumb, - timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset, + breadcrumb, timeoutMs); } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -957,36 +687,42 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials, + breadcrumb, timeoutMs); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -995,52 +731,67 @@ namespace WindowCovering { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; { switch (aCommandId) { case ZCL_WINDOW_COVERING_DOWN_CLOSE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfWindowCoveringClusterWindowCoveringDownCloseCallback(apCommandObj); + wasHandled = emberAfWindowCoveringClusterWindowCoveringDownCloseCallback(apCommandObj); break; } case ZCL_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t percentageLiftValue; - bool percentageLiftValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (percentageLiftValueExists) + 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; } - TLVUnpackError = aDataTlv.Get(percentageLiftValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - percentageLiftValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(percentageLiftValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1050,64 +801,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfWindowCoveringClusterWindowCoveringGoToLiftPercentageCallback(apCommandObj, percentageLiftValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfWindowCoveringClusterWindowCoveringGoToLiftPercentageCallback(apCommandObj, percentageLiftValue); } break; } case ZCL_WINDOW_COVERING_GO_TO_LIFT_VALUE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t liftValue; - bool liftValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (liftValueExists) + 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; } - TLVUnpackError = aDataTlv.Get(liftValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - liftValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(liftValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1117,64 +861,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfWindowCoveringClusterWindowCoveringGoToLiftValueCallback(apCommandObj, liftValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfWindowCoveringClusterWindowCoveringGoToLiftValueCallback(apCommandObj, liftValue); } break; } case ZCL_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t percentageTiltValue; - bool percentageTiltValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (percentageTiltValueExists) + 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; } - TLVUnpackError = aDataTlv.Get(percentageTiltValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - percentageTiltValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(percentageTiltValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1184,64 +920,57 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfWindowCoveringClusterWindowCoveringGoToTiltPercentageCallback(apCommandObj, percentageTiltValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfWindowCoveringClusterWindowCoveringGoToTiltPercentageCallback(apCommandObj, percentageTiltValue); } break; } case ZCL_WINDOW_COVERING_GO_TO_TILT_VALUE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t tiltValue; - bool tiltValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (tiltValueExists) + 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; } - TLVUnpackError = aDataTlv.Get(tiltValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - tiltValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(tiltValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1251,48 +980,53 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfWindowCoveringClusterWindowCoveringGoToTiltValueCallback(apCommandObj, tiltValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfWindowCoveringClusterWindowCoveringGoToTiltValueCallback(apCommandObj, tiltValue); } break; } case ZCL_WINDOW_COVERING_STOP_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfWindowCoveringClusterWindowCoveringStopCallback(apCommandObj); + wasHandled = emberAfWindowCoveringClusterWindowCoveringStopCallback(apCommandObj); break; } case ZCL_WINDOW_COVERING_UP_OPEN_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. - emberAfWindowCoveringClusterWindowCoveringUpOpenCallback(apCommandObj); + wasHandled = emberAfWindowCoveringClusterWindowCoveringUpOpenCallback(apCommandObj); break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_WINDOW_COVERING_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_WINDOW_COVERING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_WINDOW_COVERING_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace WindowCovering @@ -1317,8 +1051,13 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/src/controller/python/chip/clusters/CHIPClusters.cpp b/src/controller/python/chip/clusters/CHIPClusters.cpp index 1d653bdfbebc8c..9183aa435e42a0 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.cpp +++ b/src/controller/python/chip/clusters/CHIPClusters.cpp @@ -97,8 +97,7 @@ CHIP_ERROR chip_ime_AppendCommand_AccountLogin_GetSetupPIN(chip::Controller::Dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::AccountLoginCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetSetupPIN(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(tempAccountIdentifier, tempAccountIdentifier_Len)); + return cluster.GetSetupPIN(nullptr, nullptr, chip::ByteSpan(tempAccountIdentifier, tempAccountIdentifier_Len)); } CHIP_ERROR chip_ime_AppendCommand_AccountLogin_Login(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, const uint8_t * tempAccountIdentifier, @@ -108,8 +107,8 @@ CHIP_ERROR chip_ime_AppendCommand_AccountLogin_Login(chip::Controller::Device * VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::AccountLoginCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Login(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(tempAccountIdentifier, tempAccountIdentifier_Len), chip::ByteSpan(setupPIN, setupPIN_Len)); + return cluster.Login(nullptr, nullptr, chip::ByteSpan(tempAccountIdentifier, tempAccountIdentifier_Len), + chip::ByteSpan(setupPIN, setupPIN_Len)); } CHIP_ERROR chip_ime_ReadAttribute_AccountLogin_ClusterRevision(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -207,8 +206,8 @@ CHIP_ERROR chip_ime_AppendCommand_ApplicationLauncher_LaunchApp(chip::Controller VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ApplicationLauncherCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.LaunchApp(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), chip::ByteSpan(data, data_Len), - catalogVendorId, chip::ByteSpan(applicationId, applicationId_Len)); + return cluster.LaunchApp(nullptr, nullptr, chip::ByteSpan(data, data_Len), catalogVendorId, + chip::ByteSpan(applicationId, applicationId_Len)); } CHIP_ERROR chip_ime_ReadAttribute_ApplicationLauncher_ApplicationLauncherList(chip::Controller::Device * device, @@ -240,8 +239,7 @@ CHIP_ERROR chip_ime_AppendCommand_AudioOutput_RenameOutput(chip::Controller::Dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::AudioOutputCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RenameOutput(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), index, - chip::ByteSpan(name, name_Len)); + return cluster.RenameOutput(nullptr, nullptr, index, chip::ByteSpan(name, name_Len)); } CHIP_ERROR chip_ime_AppendCommand_AudioOutput_SelectOutput(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t index) @@ -249,7 +247,7 @@ CHIP_ERROR chip_ime_AppendCommand_AudioOutput_SelectOutput(chip::Controller::Dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::AudioOutputCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SelectOutput(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), index); + return cluster.SelectOutput(nullptr, nullptr, index); } CHIP_ERROR chip_ime_ReadAttribute_AudioOutput_AudioOutputList(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -280,7 +278,7 @@ CHIP_ERROR chip_ime_AppendCommand_BarrierControl_BarrierControlGoToPercent(chip: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::BarrierControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.BarrierControlGoToPercent(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), percentOpen); + return cluster.BarrierControlGoToPercent(nullptr, nullptr, percentOpen); } CHIP_ERROR chip_ime_AppendCommand_BarrierControl_BarrierControlStop(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -288,7 +286,7 @@ CHIP_ERROR chip_ime_AppendCommand_BarrierControl_BarrierControlStop(chip::Contro VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::BarrierControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.BarrierControlStop(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.BarrierControlStop(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_BarrierControl_BarrierMovingState(chip::Controller::Device * device, @@ -345,7 +343,7 @@ CHIP_ERROR chip_ime_AppendCommand_Basic_MfgSpecificPing(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::BasicCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MfgSpecificPing(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MfgSpecificPing(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_Basic_InteractionModelVersion(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -520,7 +518,7 @@ CHIP_ERROR chip_ime_AppendCommand_Binding_Bind(chip::Controller::Device * device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::BindingCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Bind(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), nodeId, groupId, endpointId, clusterId); + return cluster.Bind(nullptr, nullptr, nodeId, groupId, endpointId, clusterId); } CHIP_ERROR chip_ime_AppendCommand_Binding_Unbind(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, @@ -529,8 +527,7 @@ CHIP_ERROR chip_ime_AppendCommand_Binding_Unbind(chip::Controller::Device * devi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::BindingCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Unbind(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), nodeId, groupId, endpointId, - clusterId); + return cluster.Unbind(nullptr, nullptr, nodeId, groupId, endpointId, clusterId); } CHIP_ERROR chip_ime_ReadAttribute_Binding_ClusterRevision(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -552,8 +549,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveColor(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveColor(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), rateX, rateY, optionsMask, - optionsOverride); + return cluster.MoveColor(nullptr, nullptr, rateX, rateY, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveColorTemperature(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t moveMode, @@ -564,8 +560,8 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveColorTemperature(chip::Contro VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveColorTemperature(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), moveMode, rate, - colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); + return cluster.MoveColorTemperature(nullptr, nullptr, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, + optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveHue(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, @@ -574,8 +570,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveHue(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveHue(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), moveMode, rate, optionsMask, - optionsOverride); + return cluster.MoveHue(nullptr, nullptr, moveMode, rate, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveSaturation(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, @@ -584,8 +579,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveSaturation(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveSaturation(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), moveMode, rate, optionsMask, - optionsOverride); + return cluster.MoveSaturation(nullptr, nullptr, moveMode, rate, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToColor(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t colorX, uint16_t colorY, uint16_t transitionTime, @@ -594,8 +588,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToColor(chip::Controller::Dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveToColor(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), colorX, colorY, transitionTime, - optionsMask, optionsOverride); + return cluster.MoveToColor(nullptr, nullptr, colorX, colorY, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToColorTemperature(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -605,8 +598,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToColorTemperature(chip::Cont VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveToColorTemperature(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), colorTemperature, - transitionTime, optionsMask, optionsOverride); + return cluster.MoveToColorTemperature(nullptr, nullptr, colorTemperature, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToHue(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t hue, uint8_t direction, uint16_t transitionTime, @@ -615,8 +607,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToHue(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveToHue(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), hue, direction, transitionTime, - optionsMask, optionsOverride); + return cluster.MoveToHue(nullptr, nullptr, hue, direction, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToHueAndSaturation(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t hue, @@ -626,8 +617,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToHueAndSaturation(chip::Cont VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveToHueAndSaturation(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), hue, saturation, - transitionTime, optionsMask, optionsOverride); + return cluster.MoveToHueAndSaturation(nullptr, nullptr, hue, saturation, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToSaturation(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t saturation, uint16_t transitionTime, @@ -636,8 +626,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_MoveToSaturation(chip::Controller VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveToSaturation(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), saturation, transitionTime, - optionsMask, optionsOverride); + return cluster.MoveToSaturation(nullptr, nullptr, saturation, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepColor(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, int16_t stepX, int16_t stepY, uint16_t transitionTime, @@ -646,8 +635,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepColor(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StepColor(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), stepX, stepY, transitionTime, - optionsMask, optionsOverride); + return cluster.StepColor(nullptr, nullptr, stepX, stepY, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepColorTemperature(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t stepMode, @@ -659,9 +647,8 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepColorTemperature(chip::Contro VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StepColorTemperature(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), stepMode, stepSize, - transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, - optionsOverride); + return cluster.StepColorTemperature(nullptr, nullptr, stepMode, stepSize, transitionTime, colorTemperatureMinimum, + colorTemperatureMaximum, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepHue(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, @@ -670,8 +657,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepHue(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StepHue(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), stepMode, stepSize, transitionTime, - optionsMask, optionsOverride); + return cluster.StepHue(nullptr, nullptr, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepSaturation(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t stepMode, uint8_t stepSize, @@ -680,8 +666,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_StepSaturation(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StepSaturation(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), stepMode, stepSize, - transitionTime, optionsMask, optionsOverride); + return cluster.StepSaturation(nullptr, nullptr, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_AppendCommand_ColorControl_StopMoveStep(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t optionsMask, uint8_t optionsOverride) @@ -689,7 +674,7 @@ CHIP_ERROR chip_ime_AppendCommand_ColorControl_StopMoveStep(chip::Controller::De VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ColorControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StopMoveStep(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), optionsMask, optionsOverride); + return cluster.StopMoveStep(nullptr, nullptr, optionsMask, optionsOverride); } CHIP_ERROR chip_ime_ReadAttribute_ColorControl_CurrentHue(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1211,8 +1196,7 @@ CHIP_ERROR chip_ime_AppendCommand_ContentLaunch_LaunchContent(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ContentLaunchCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.LaunchContent(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), autoPlay, - chip::ByteSpan(data, data_Len)); + return cluster.LaunchContent(nullptr, nullptr, autoPlay, chip::ByteSpan(data, data_Len)); } CHIP_ERROR chip_ime_AppendCommand_ContentLaunch_LaunchURL(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, const uint8_t * contentURL, uint32_t contentURL_Len, @@ -1221,8 +1205,8 @@ CHIP_ERROR chip_ime_AppendCommand_ContentLaunch_LaunchURL(chip::Controller::Devi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ContentLaunchCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.LaunchURL(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(contentURL, contentURL_Len), chip::ByteSpan(displayString, displayString_Len)); + return cluster.LaunchURL(nullptr, nullptr, chip::ByteSpan(contentURL, contentURL_Len), + chip::ByteSpan(displayString, displayString_Len)); } CHIP_ERROR chip_ime_ReadAttribute_ContentLaunch_AcceptsHeaderList(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1274,7 +1258,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearAllPins(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearAllPins(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.ClearAllPins(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearAllRfids(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1282,7 +1266,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearAllRfids(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearAllRfids(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.ClearAllRfids(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearHolidaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId) @@ -1290,7 +1274,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearHolidaySchedule(chip::Controller VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearHolidaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId); + return cluster.ClearHolidaySchedule(nullptr, nullptr, scheduleId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearPin(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId) @@ -1298,7 +1282,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearPin(chip::Controller::Device * d VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearPin(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId); + return cluster.ClearPin(nullptr, nullptr, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearRfid(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId) @@ -1306,7 +1290,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearRfid(chip::Controller::Device * VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearRfid(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId); + return cluster.ClearRfid(nullptr, nullptr, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearWeekdaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId, uint16_t userId) @@ -1314,7 +1298,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearWeekdaySchedule(chip::Controller VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearWeekdaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId, userId); + return cluster.ClearWeekdaySchedule(nullptr, nullptr, scheduleId, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearYeardaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId, uint16_t userId) @@ -1322,7 +1306,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearYeardaySchedule(chip::Controller VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearYeardaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId, userId); + return cluster.ClearYeardaySchedule(nullptr, nullptr, scheduleId, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetHolidaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId) @@ -1330,7 +1314,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetHolidaySchedule(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetHolidaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId); + return cluster.GetHolidaySchedule(nullptr, nullptr, scheduleId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetLogRecord(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t logIndex) @@ -1338,7 +1322,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetLogRecord(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetLogRecord(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), logIndex); + return cluster.GetLogRecord(nullptr, nullptr, logIndex); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetPin(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId) @@ -1346,7 +1330,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetPin(chip::Controller::Device * dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetPin(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId); + return cluster.GetPin(nullptr, nullptr, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetRfid(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId) @@ -1354,7 +1338,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetRfid(chip::Controller::Device * de VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetRfid(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId); + return cluster.GetRfid(nullptr, nullptr, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetUserType(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId) @@ -1362,7 +1346,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetUserType(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetUserType(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId); + return cluster.GetUserType(nullptr, nullptr, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetWeekdaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId, uint16_t userId) @@ -1370,7 +1354,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetWeekdaySchedule(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetWeekdaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId, userId); + return cluster.GetWeekdaySchedule(nullptr, nullptr, scheduleId, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetYeardaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId, uint16_t userId) @@ -1378,7 +1362,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_GetYeardaySchedule(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetYeardaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId, userId); + return cluster.GetYeardaySchedule(nullptr, nullptr, scheduleId, userId); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_LockDoor(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, const uint8_t * pin, uint32_t pin_Len) @@ -1386,7 +1370,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_LockDoor(chip::Controller::Device * d VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.LockDoor(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), chip::ByteSpan(pin, pin_Len)); + return cluster.LockDoor(nullptr, nullptr, chip::ByteSpan(pin, pin_Len)); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetHolidaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId, uint32_t localStartTime, @@ -1395,8 +1379,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetHolidaySchedule(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetHolidaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId, - localStartTime, localEndTime, operatingModeDuringHoliday); + return cluster.SetHolidaySchedule(nullptr, nullptr, scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetPin(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId, uint8_t userStatus, uint8_t userType, const uint8_t * pin, @@ -1405,8 +1388,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetPin(chip::Controller::Device * dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetPin(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId, userStatus, userType, - chip::ByteSpan(pin, pin_Len)); + return cluster.SetPin(nullptr, nullptr, userId, userStatus, userType, chip::ByteSpan(pin, pin_Len)); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetRfid(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId, uint8_t userStatus, uint8_t userType, const uint8_t * id, @@ -1415,8 +1397,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetRfid(chip::Controller::Device * de VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetRfid(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId, userStatus, userType, - chip::ByteSpan(id, id_Len)); + return cluster.SetRfid(nullptr, nullptr, userId, userStatus, userType, chip::ByteSpan(id, id_Len)); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetUserType(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t userId, uint8_t userType) @@ -1424,7 +1405,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetUserType(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetUserType(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), userId, userType); + return cluster.SetUserType(nullptr, nullptr, userId, userType); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetWeekdaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId, uint16_t userId, uint8_t daysMask, @@ -1434,8 +1415,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetWeekdaySchedule(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetWeekdaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId, userId, - daysMask, startHour, startMinute, endHour, endMinute); + return cluster.SetWeekdaySchedule(nullptr, nullptr, scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetYeardaySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t scheduleId, uint16_t userId, @@ -1444,8 +1424,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_SetYeardaySchedule(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetYeardaySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), scheduleId, userId, - localStartTime, localEndTime); + return cluster.SetYeardaySchedule(nullptr, nullptr, scheduleId, userId, localStartTime, localEndTime); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_UnlockDoor(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, const uint8_t * pin, uint32_t pin_Len) @@ -1453,7 +1432,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_UnlockDoor(chip::Controller::Device * VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.UnlockDoor(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), chip::ByteSpan(pin, pin_Len)); + return cluster.UnlockDoor(nullptr, nullptr, chip::ByteSpan(pin, pin_Len)); } CHIP_ERROR chip_ime_AppendCommand_DoorLock_UnlockWithTimeout(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t timeoutInSeconds, const uint8_t * pin, @@ -1462,8 +1441,7 @@ CHIP_ERROR chip_ime_AppendCommand_DoorLock_UnlockWithTimeout(chip::Controller::D VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::DoorLockCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.UnlockWithTimeout(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), timeoutInSeconds, - chip::ByteSpan(pin, pin_Len)); + return cluster.UnlockWithTimeout(nullptr, nullptr, timeoutInSeconds, chip::ByteSpan(pin, pin_Len)); } CHIP_ERROR chip_ime_ReadAttribute_DoorLock_LockState(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1522,8 +1500,7 @@ CHIP_ERROR chip_ime_AppendCommand_GeneralCommissioning_ArmFailSafe(chip::Control VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GeneralCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ArmFailSafe(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), expiryLengthSeconds, breadcrumb, - timeoutMs); + return cluster.ArmFailSafe(nullptr, nullptr, expiryLengthSeconds, breadcrumb, timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_GeneralCommissioning_CommissioningComplete(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1531,7 +1508,7 @@ CHIP_ERROR chip_ime_AppendCommand_GeneralCommissioning_CommissioningComplete(chi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GeneralCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.CommissioningComplete(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.CommissioningComplete(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_GeneralCommissioning_SetRegulatoryConfig(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -1542,8 +1519,8 @@ CHIP_ERROR chip_ime_AppendCommand_GeneralCommissioning_SetRegulatoryConfig(chip: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GeneralCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetRegulatoryConfig(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), location, - chip::ByteSpan(countryCode, countryCode_Len), breadcrumb, timeoutMs); + return cluster.SetRegulatoryConfig(nullptr, nullptr, location, chip::ByteSpan(countryCode, countryCode_Len), breadcrumb, + timeoutMs); } CHIP_ERROR chip_ime_ReadAttribute_GeneralCommissioning_FabricId(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1595,8 +1572,7 @@ CHIP_ERROR chip_ime_AppendCommand_Groups_AddGroup(chip::Controller::Device * dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GroupsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.AddGroup(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId, - chip::ByteSpan(groupName, groupName_Len)); + return cluster.AddGroup(nullptr, nullptr, groupId, chip::ByteSpan(groupName, groupName_Len)); } CHIP_ERROR chip_ime_AppendCommand_Groups_AddGroupIfIdentifying(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId, const uint8_t * groupName, @@ -1605,8 +1581,7 @@ CHIP_ERROR chip_ime_AppendCommand_Groups_AddGroupIfIdentifying(chip::Controller: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GroupsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.AddGroupIfIdentifying(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId, - chip::ByteSpan(groupName, groupName_Len)); + return cluster.AddGroupIfIdentifying(nullptr, nullptr, groupId, chip::ByteSpan(groupName, groupName_Len)); } CHIP_ERROR chip_ime_AppendCommand_Groups_GetGroupMembership(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t groupCount, uint16_t groupList) @@ -1614,7 +1589,7 @@ CHIP_ERROR chip_ime_AppendCommand_Groups_GetGroupMembership(chip::Controller::De VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GroupsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetGroupMembership(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupCount, groupList); + return cluster.GetGroupMembership(nullptr, nullptr, groupCount, groupList); } CHIP_ERROR chip_ime_AppendCommand_Groups_RemoveAllGroups(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1622,7 +1597,7 @@ CHIP_ERROR chip_ime_AppendCommand_Groups_RemoveAllGroups(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GroupsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RemoveAllGroups(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.RemoveAllGroups(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_Groups_RemoveGroup(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId) @@ -1630,7 +1605,7 @@ CHIP_ERROR chip_ime_AppendCommand_Groups_RemoveGroup(chip::Controller::Device * VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GroupsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RemoveGroup(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId); + return cluster.RemoveGroup(nullptr, nullptr, groupId); } CHIP_ERROR chip_ime_AppendCommand_Groups_ViewGroup(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId) @@ -1638,7 +1613,7 @@ CHIP_ERROR chip_ime_AppendCommand_Groups_ViewGroup(chip::Controller::Device * de VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::GroupsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ViewGroup(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId); + return cluster.ViewGroup(nullptr, nullptr, groupId); } CHIP_ERROR chip_ime_ReadAttribute_Groups_NameSupport(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1668,7 +1643,7 @@ CHIP_ERROR chip_ime_AppendCommand_Identify_Identify(chip::Controller::Device * d VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::IdentifyCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Identify(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), identifyTime); + return cluster.Identify(nullptr, nullptr, identifyTime); } CHIP_ERROR chip_ime_AppendCommand_Identify_IdentifyQuery(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1676,7 +1651,7 @@ CHIP_ERROR chip_ime_AppendCommand_Identify_IdentifyQuery(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::IdentifyCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.IdentifyQuery(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.IdentifyQuery(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_Identify_IdentifyTime(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1706,7 +1681,7 @@ CHIP_ERROR chip_ime_AppendCommand_KeypadInput_SendKey(chip::Controller::Device * VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::KeypadInputCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SendKey(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), keyCode); + return cluster.SendKey(nullptr, nullptr, keyCode); } CHIP_ERROR chip_ime_ReadAttribute_KeypadInput_ClusterRevision(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1728,8 +1703,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_Move(chip::Controller::Device * d VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Move(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), moveMode, rate, optionMask, - optionOverride); + return cluster.Move(nullptr, nullptr, moveMode, rate, optionMask, optionOverride); } CHIP_ERROR chip_ime_AppendCommand_LevelControl_MoveToLevel(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t level, uint16_t transitionTime, @@ -1738,8 +1712,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_MoveToLevel(chip::Controller::Dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveToLevel(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), level, transitionTime, - optionMask, optionOverride); + return cluster.MoveToLevel(nullptr, nullptr, level, transitionTime, optionMask, optionOverride); } CHIP_ERROR chip_ime_AppendCommand_LevelControl_MoveToLevelWithOnOff(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t level, @@ -1748,7 +1721,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_MoveToLevelWithOnOff(chip::Contro VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveToLevelWithOnOff(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), level, transitionTime); + return cluster.MoveToLevelWithOnOff(nullptr, nullptr, level, transitionTime); } CHIP_ERROR chip_ime_AppendCommand_LevelControl_MoveWithOnOff(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t moveMode, uint8_t rate) @@ -1756,7 +1729,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_MoveWithOnOff(chip::Controller::D VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MoveWithOnOff(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), moveMode, rate); + return cluster.MoveWithOnOff(nullptr, nullptr, moveMode, rate); } CHIP_ERROR chip_ime_AppendCommand_LevelControl_Step(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, @@ -1765,8 +1738,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_Step(chip::Controller::Device * d VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Step(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), stepMode, stepSize, transitionTime, - optionMask, optionOverride); + return cluster.Step(nullptr, nullptr, stepMode, stepSize, transitionTime, optionMask, optionOverride); } CHIP_ERROR chip_ime_AppendCommand_LevelControl_StepWithOnOff(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t stepMode, uint8_t stepSize, @@ -1775,8 +1747,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_StepWithOnOff(chip::Controller::D VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StepWithOnOff(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), stepMode, stepSize, - transitionTime); + return cluster.StepWithOnOff(nullptr, nullptr, stepMode, stepSize, transitionTime); } CHIP_ERROR chip_ime_AppendCommand_LevelControl_Stop(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t optionMask, uint8_t optionOverride) @@ -1784,7 +1755,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_Stop(chip::Controller::Device * d VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Stop(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), optionMask, optionOverride); + return cluster.Stop(nullptr, nullptr, optionMask, optionOverride); } CHIP_ERROR chip_ime_AppendCommand_LevelControl_StopWithOnOff(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1792,7 +1763,7 @@ CHIP_ERROR chip_ime_AppendCommand_LevelControl_StopWithOnOff(chip::Controller::D VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LevelControlCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StopWithOnOff(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.StopWithOnOff(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_LevelControl_CurrentLevel(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1830,7 +1801,7 @@ CHIP_ERROR chip_ime_AppendCommand_LowPower_Sleep(chip::Controller::Device * devi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::LowPowerCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Sleep(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.Sleep(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_LowPower_ClusterRevision(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1851,7 +1822,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaInput_HideInputStatus(chip::Controller::D VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaInputCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.HideInputStatus(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.HideInputStatus(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaInput_RenameInput(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t index, const uint8_t * name, uint32_t name_Len) @@ -1859,8 +1830,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaInput_RenameInput(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaInputCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RenameInput(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), index, - chip::ByteSpan(name, name_Len)); + return cluster.RenameInput(nullptr, nullptr, index, chip::ByteSpan(name, name_Len)); } CHIP_ERROR chip_ime_AppendCommand_MediaInput_SelectInput(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t index) @@ -1868,7 +1838,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaInput_SelectInput(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaInputCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SelectInput(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), index); + return cluster.SelectInput(nullptr, nullptr, index); } CHIP_ERROR chip_ime_AppendCommand_MediaInput_ShowInputStatus(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1876,7 +1846,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaInput_ShowInputStatus(chip::Controller::D VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaInputCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ShowInputStatus(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.ShowInputStatus(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_MediaInput_MediaInputList(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -1906,7 +1876,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaFastForward(chip::Controlle VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaFastForward(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaFastForward(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaNext(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1914,7 +1884,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaNext(chip::Controller::Devi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaNext(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaNext(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaPause(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1922,7 +1892,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaPause(chip::Controller::Dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaPause(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaPause(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaPlay(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1930,7 +1900,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaPlay(chip::Controller::Devi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaPlay(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaPlay(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaPrevious(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1938,7 +1908,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaPrevious(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaPrevious(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaPrevious(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaRewind(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1946,7 +1916,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaRewind(chip::Controller::De VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaRewind(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaRewind(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaSkipBackward(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint64_t deltaPositionMilliseconds) @@ -1954,7 +1924,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaSkipBackward(chip::Controll VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaSkipBackward(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), deltaPositionMilliseconds); + return cluster.MediaSkipBackward(nullptr, nullptr, deltaPositionMilliseconds); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaSkipForward(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint64_t deltaPositionMilliseconds) @@ -1962,7 +1932,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaSkipForward(chip::Controlle VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaSkipForward(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), deltaPositionMilliseconds); + return cluster.MediaSkipForward(nullptr, nullptr, deltaPositionMilliseconds); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaSkipSeek(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint64_t position) @@ -1970,7 +1940,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaSkipSeek(chip::Controller:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaSkipSeek(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), position); + return cluster.MediaSkipSeek(nullptr, nullptr, position); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaStartOver(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1978,7 +1948,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaStartOver(chip::Controller: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaStartOver(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaStartOver(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaStop(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -1986,7 +1956,7 @@ CHIP_ERROR chip_ime_AppendCommand_MediaPlayback_MediaStop(chip::Controller::Devi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::MediaPlaybackCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.MediaStop(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.MediaStop(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_MediaPlayback_ClusterRevision(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -2010,8 +1980,8 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_AddThreadNetwork(chip::Co VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.AddThreadNetwork(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(operationalDataset, operationalDataset_Len), breadcrumb, timeoutMs); + return cluster.AddThreadNetwork(nullptr, nullptr, chip::ByteSpan(operationalDataset, operationalDataset_Len), breadcrumb, + timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_AddWiFiNetwork(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2022,9 +1992,8 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_AddWiFiNetwork(chip::Cont VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.AddWiFiNetwork(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(ssid, ssid_Len), chip::ByteSpan(credentials, credentials_Len), breadcrumb, - timeoutMs); + return cluster.AddWiFiNetwork(nullptr, nullptr, chip::ByteSpan(ssid, ssid_Len), chip::ByteSpan(credentials, credentials_Len), + breadcrumb, timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_DisableNetwork(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2034,8 +2003,7 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_DisableNetwork(chip::Cont VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.DisableNetwork(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(networkID, networkID_Len), breadcrumb, timeoutMs); + return cluster.DisableNetwork(nullptr, nullptr, chip::ByteSpan(networkID, networkID_Len), breadcrumb, timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_EnableNetwork(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2045,8 +2013,7 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_EnableNetwork(chip::Contr VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.EnableNetwork(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(networkID, networkID_Len), breadcrumb, timeoutMs); + return cluster.EnableNetwork(nullptr, nullptr, chip::ByteSpan(networkID, networkID_Len), breadcrumb, timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_GetLastNetworkCommissioningResult(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -2055,7 +2022,7 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_GetLastNetworkCommissioni VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetLastNetworkCommissioningResult(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), timeoutMs); + return cluster.GetLastNetworkCommissioningResult(nullptr, nullptr, timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_RemoveNetwork(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2065,8 +2032,7 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_RemoveNetwork(chip::Contr VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RemoveNetwork(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(networkID, networkID_Len), breadcrumb, timeoutMs); + return cluster.RemoveNetwork(nullptr, nullptr, chip::ByteSpan(networkID, networkID_Len), breadcrumb, timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_ScanNetworks(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2076,8 +2042,7 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_ScanNetworks(chip::Contro VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ScanNetworks(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), chip::ByteSpan(ssid, ssid_Len), - breadcrumb, timeoutMs); + return cluster.ScanNetworks(nullptr, nullptr, chip::ByteSpan(ssid, ssid_Len), breadcrumb, timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_UpdateThreadNetwork(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2088,8 +2053,8 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_UpdateThreadNetwork(chip: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.UpdateThreadNetwork(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(operationalDataset, operationalDataset_Len), breadcrumb, timeoutMs); + return cluster.UpdateThreadNetwork(nullptr, nullptr, chip::ByteSpan(operationalDataset, operationalDataset_Len), breadcrumb, + timeoutMs); } CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_UpdateWiFiNetwork(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2100,9 +2065,8 @@ CHIP_ERROR chip_ime_AppendCommand_NetworkCommissioning_UpdateWiFiNetwork(chip::C VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::NetworkCommissioningCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.UpdateWiFiNetwork(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(ssid, ssid_Len), chip::ByteSpan(credentials, credentials_Len), breadcrumb, - timeoutMs); + return cluster.UpdateWiFiNetwork(nullptr, nullptr, chip::ByteSpan(ssid, ssid_Len), chip::ByteSpan(credentials, credentials_Len), + breadcrumb, timeoutMs); } CHIP_ERROR chip_ime_ReadAttribute_NetworkCommissioning_ClusterRevision(chip::Controller::Device * device, @@ -2123,21 +2087,21 @@ CHIP_ERROR chip_ime_AppendCommand_OnOff_Off(chip::Controller::Device * device, c VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OnOffCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Off(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.Off(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_OnOff_On(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) { VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OnOffCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.On(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.On(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_OnOff_Toggle(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) { VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OnOffCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Toggle(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.Toggle(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_OnOff_OnOff(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -2180,9 +2144,8 @@ CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_AddOpCert(chip::Control VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.AddOpCert(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), chip::ByteSpan(noc, noc_Len), - chip::ByteSpan(iCACertificate, iCACertificate_Len), chip::ByteSpan(iPKValue, iPKValue_Len), - caseAdminNode, adminVendorId); + return cluster.AddOpCert(nullptr, nullptr, chip::ByteSpan(noc, noc_Len), chip::ByteSpan(iCACertificate, iCACertificate_Len), + chip::ByteSpan(iPKValue, iPKValue_Len), caseAdminNode, adminVendorId); } CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_OpCSRRequest(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2191,8 +2154,7 @@ CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_OpCSRRequest(chip::Cont VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.OpCSRRequest(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(cSRNonce, cSRNonce_Len)); + return cluster.OpCSRRequest(nullptr, nullptr, chip::ByteSpan(cSRNonce, cSRNonce_Len)); } CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_RemoveAllFabrics(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -2200,7 +2162,7 @@ CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_RemoveAllFabrics(chip:: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RemoveAllFabrics(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.RemoveAllFabrics(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_RemoveFabric(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2210,7 +2172,7 @@ CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_RemoveFabric(chip::Cont VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RemoveFabric(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), fabricId, nodeId, vendorId); + return cluster.RemoveFabric(nullptr, nullptr, fabricId, nodeId, vendorId); } CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_SetFabric(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t vendorId) @@ -2218,7 +2180,7 @@ CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_SetFabric(chip::Control VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetFabric(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), vendorId); + return cluster.SetFabric(nullptr, nullptr, vendorId); } CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_UpdateFabricLabel(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2227,8 +2189,7 @@ CHIP_ERROR chip_ime_AppendCommand_OperationalCredentials_UpdateFabricLabel(chip: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::OperationalCredentialsCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.UpdateFabricLabel(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(label, label_Len)); + return cluster.UpdateFabricLabel(nullptr, nullptr, chip::ByteSpan(label, label_Len)); } CHIP_ERROR chip_ime_ReadAttribute_OperationalCredentials_ClusterRevision(chip::Controller::Device * device, @@ -2345,8 +2306,8 @@ CHIP_ERROR chip_ime_AppendCommand_Scenes_AddScene(chip::Controller::Device * dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ScenesCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.AddScene(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId, sceneId, transitionTime, - chip::ByteSpan(sceneName, sceneName_Len), clusterId, length, value); + return cluster.AddScene(nullptr, nullptr, groupId, sceneId, transitionTime, chip::ByteSpan(sceneName, sceneName_Len), clusterId, + length, value); } CHIP_ERROR chip_ime_AppendCommand_Scenes_GetSceneMembership(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId) @@ -2354,7 +2315,7 @@ CHIP_ERROR chip_ime_AppendCommand_Scenes_GetSceneMembership(chip::Controller::De VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ScenesCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetSceneMembership(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId); + return cluster.GetSceneMembership(nullptr, nullptr, groupId); } CHIP_ERROR chip_ime_AppendCommand_Scenes_RecallScene(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime) @@ -2362,8 +2323,7 @@ CHIP_ERROR chip_ime_AppendCommand_Scenes_RecallScene(chip::Controller::Device * VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ScenesCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RecallScene(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId, sceneId, - transitionTime); + return cluster.RecallScene(nullptr, nullptr, groupId, sceneId, transitionTime); } CHIP_ERROR chip_ime_AppendCommand_Scenes_RemoveAllScenes(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId) @@ -2371,7 +2331,7 @@ CHIP_ERROR chip_ime_AppendCommand_Scenes_RemoveAllScenes(chip::Controller::Devic VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ScenesCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RemoveAllScenes(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId); + return cluster.RemoveAllScenes(nullptr, nullptr, groupId); } CHIP_ERROR chip_ime_AppendCommand_Scenes_RemoveScene(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId, uint8_t sceneId) @@ -2379,7 +2339,7 @@ CHIP_ERROR chip_ime_AppendCommand_Scenes_RemoveScene(chip::Controller::Device * VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ScenesCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.RemoveScene(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId, sceneId); + return cluster.RemoveScene(nullptr, nullptr, groupId, sceneId); } CHIP_ERROR chip_ime_AppendCommand_Scenes_StoreScene(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId, uint8_t sceneId) @@ -2387,7 +2347,7 @@ CHIP_ERROR chip_ime_AppendCommand_Scenes_StoreScene(chip::Controller::Device * d VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ScenesCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.StoreScene(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId, sceneId); + return cluster.StoreScene(nullptr, nullptr, groupId, sceneId); } CHIP_ERROR chip_ime_AppendCommand_Scenes_ViewScene(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t groupId, uint8_t sceneId) @@ -2395,7 +2355,7 @@ CHIP_ERROR chip_ime_AppendCommand_Scenes_ViewScene(chip::Controller::Device * de VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ScenesCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ViewScene(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), groupId, sceneId); + return cluster.ViewScene(nullptr, nullptr, groupId, sceneId); } CHIP_ERROR chip_ime_ReadAttribute_Scenes_SceneCount(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -2500,8 +2460,7 @@ CHIP_ERROR chip_ime_AppendCommand_TvChannel_ChangeChannel(chip::Controller::Devi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::TvChannelCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ChangeChannel(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - chip::ByteSpan(match, match_Len)); + return cluster.ChangeChannel(nullptr, nullptr, chip::ByteSpan(match, match_Len)); } CHIP_ERROR chip_ime_AppendCommand_TvChannel_ChangeChannelByNumber(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t majorNumber, uint16_t minorNumber) @@ -2509,8 +2468,7 @@ CHIP_ERROR chip_ime_AppendCommand_TvChannel_ChangeChannelByNumber(chip::Controll VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::TvChannelCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ChangeChannelByNumber(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), majorNumber, - minorNumber); + return cluster.ChangeChannelByNumber(nullptr, nullptr, majorNumber, minorNumber); } CHIP_ERROR chip_ime_AppendCommand_TvChannel_SkipChannel(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t count) @@ -2518,7 +2476,7 @@ CHIP_ERROR chip_ime_AppendCommand_TvChannel_SkipChannel(chip::Controller::Device VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::TvChannelCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SkipChannel(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), count); + return cluster.SkipChannel(nullptr, nullptr, count); } CHIP_ERROR chip_ime_ReadAttribute_TvChannel_TvChannelList(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -2567,8 +2525,7 @@ CHIP_ERROR chip_ime_AppendCommand_TargetNavigator_NavigateTarget(chip::Controlle VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::TargetNavigatorCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.NavigateTarget(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), target, - chip::ByteSpan(data, data_Len)); + return cluster.NavigateTarget(nullptr, nullptr, target, chip::ByteSpan(data, data_Len)); } CHIP_ERROR chip_ime_ReadAttribute_TargetNavigator_TargetNavigatorList(chip::Controller::Device * device, @@ -2651,7 +2608,7 @@ CHIP_ERROR chip_ime_AppendCommand_TestCluster_Test(chip::Controller::Device * de VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::TestClusterCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.Test(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.Test(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_TestCluster_TestNotHandled(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -2659,7 +2616,7 @@ CHIP_ERROR chip_ime_AppendCommand_TestCluster_TestNotHandled(chip::Controller::D VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::TestClusterCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.TestNotHandled(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.TestNotHandled(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_TestCluster_TestSpecific(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -2667,7 +2624,7 @@ CHIP_ERROR chip_ime_AppendCommand_TestCluster_TestSpecific(chip::Controller::Dev VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::TestClusterCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.TestSpecific(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.TestSpecific(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_TestCluster_Boolean(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -2832,7 +2789,7 @@ CHIP_ERROR chip_ime_AppendCommand_Thermostat_ClearWeeklySchedule(chip::Controlle VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ThermostatCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.ClearWeeklySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.ClearWeeklySchedule(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_Thermostat_GetRelayStatusLog(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -2840,7 +2797,7 @@ CHIP_ERROR chip_ime_AppendCommand_Thermostat_GetRelayStatusLog(chip::Controller: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ThermostatCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetRelayStatusLog(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.GetRelayStatusLog(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_Thermostat_GetWeeklySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t daysToReturn, uint8_t modeToReturn) @@ -2848,8 +2805,7 @@ CHIP_ERROR chip_ime_AppendCommand_Thermostat_GetWeeklySchedule(chip::Controller: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ThermostatCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.GetWeeklySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), daysToReturn, - modeToReturn); + return cluster.GetWeeklySchedule(nullptr, nullptr, daysToReturn, modeToReturn); } CHIP_ERROR chip_ime_AppendCommand_Thermostat_SetWeeklySchedule(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t numberOfTransitionsForSequence, @@ -2859,8 +2815,8 @@ CHIP_ERROR chip_ime_AppendCommand_Thermostat_SetWeeklySchedule(chip::Controller: VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ThermostatCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetWeeklySchedule(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - numberOfTransitionsForSequence, dayOfWeekForSequence, modeForSequence, payload); + return cluster.SetWeeklySchedule(nullptr, nullptr, numberOfTransitionsForSequence, dayOfWeekForSequence, modeForSequence, + payload); } CHIP_ERROR chip_ime_AppendCommand_Thermostat_SetpointRaiseLower(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t mode, int8_t amount) @@ -2868,7 +2824,7 @@ CHIP_ERROR chip_ime_AppendCommand_Thermostat_SetpointRaiseLower(chip::Controller VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::ThermostatCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.SetpointRaiseLower(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), mode, amount); + return cluster.SetpointRaiseLower(nullptr, nullptr, mode, amount); } CHIP_ERROR chip_ime_ReadAttribute_Thermostat_LocalTemperature(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, @@ -2966,7 +2922,7 @@ CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringDownClose(chip::C VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::WindowCoveringCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.WindowCoveringDownClose(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.WindowCoveringDownClose(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToLiftPercentage(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2975,8 +2931,7 @@ CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToLiftPercentag VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::WindowCoveringCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.WindowCoveringGoToLiftPercentage(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - percentageLiftValue); + return cluster.WindowCoveringGoToLiftPercentage(nullptr, nullptr, percentageLiftValue); } CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToLiftValue(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2985,7 +2940,7 @@ CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToLiftValue(chi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::WindowCoveringCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.WindowCoveringGoToLiftValue(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), liftValue); + return cluster.WindowCoveringGoToLiftValue(nullptr, nullptr, liftValue); } CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToTiltPercentage(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -2994,8 +2949,7 @@ CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToTiltPercentag VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::WindowCoveringCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.WindowCoveringGoToTiltPercentage(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), - percentageTiltValue); + return cluster.WindowCoveringGoToTiltPercentage(nullptr, nullptr, percentageTiltValue); } CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToTiltValue(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, @@ -3004,7 +2958,7 @@ CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringGoToTiltValue(chi VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::WindowCoveringCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.WindowCoveringGoToTiltValue(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel(), tiltValue); + return cluster.WindowCoveringGoToTiltValue(nullptr, nullptr, tiltValue); } CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringStop(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -3012,7 +2966,7 @@ CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringStop(chip::Contro VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::WindowCoveringCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.WindowCoveringStop(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.WindowCoveringStop(nullptr, nullptr); } CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringUpOpen(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId) @@ -3020,7 +2974,7 @@ CHIP_ERROR chip_ime_AppendCommand_WindowCovering_WindowCoveringUpOpen(chip::Cont VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); chip::Controller::WindowCoveringCluster cluster; cluster.Associate(device, ZCLendpointId); - return cluster.WindowCoveringUpOpen(gDefaultSuccessCallback.Cancel(), gDefaultFailureCallback.Cancel()); + return cluster.WindowCoveringUpOpen(nullptr, nullptr); } CHIP_ERROR chip_ime_ReadAttribute_WindowCovering_WindowCoveringType(chip::Controller::Device * device, diff --git a/src/controller/python/gen/CHIPClientCallbacks.cpp b/src/controller/python/gen/CHIPClientCallbacks.cpp index dc5ec800dfc27d..a5125621992b82 100644 --- a/src/controller/python/gen/CHIPClientCallbacks.cpp +++ b/src/controller/python/gen/CHIPClientCallbacks.cpp @@ -19,6 +19,8 @@ #include "gen/CHIPClientCallbacks.h" +#include + #include "gen/enums.h" #include #include @@ -80,6 +82,28 @@ using namespace ::chip; return true; \ } +#define GET_CLUSTER_RESPONSE_CALLBACKS(name) \ + Callback::Cancelable * onSuccessCallback = nullptr; \ + Callback::Cancelable * onFailureCallback = nullptr; \ + NodeId sourceIdentifier = reinterpret_cast(commandObj); \ + /* #6559: Currently, we only have one commands for the IMInvokeCommands and to a device, so the seqNum is always set to 0. */ \ + CHIP_ERROR err = gCallbacks.GetResponseCallback(sourceIdentifier, 0, &onSuccessCallback, &onFailureCallback); \ + \ + if (CHIP_NO_ERROR != err) \ + { \ + if (onSuccessCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing success callback", name); \ + } \ + \ + if (onFailureCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing failure callback", name); \ + } \ + \ + return true; \ + } + #define GET_REPORT_CALLBACK(name) \ Callback::Cancelable * onReportCallback = nullptr; \ CHIP_ERROR err = gCallbacks.GetReportCallback(sourceId, endpointId, clusterId, attributeId, &onReportCallback); \ @@ -94,8 +118,6 @@ using namespace ::chip; return true; \ } -extern "C" { - void LogStatus(uint8_t status) { switch (status) @@ -250,6 +272,29 @@ bool emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, Em return true; } +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status) +{ + ChipLogProgress(Zcl, "DefaultResponse:"); + ChipLogProgress(Zcl, " Transaction: %p", commandObj); + LogStatus(status); + + GET_CLUSTER_RESPONSE_CALLBACKS("emberAfDefaultResponseCallback"); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onSuccessCallback); + cb->mCall(cb->mContext); + } + else + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, static_cast(status)); + } + + return true; +} + bool emberAfReadAttributesResponseCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) { ChipLogProgress(Zcl, "ReadAttributesResponse:"); @@ -893,7 +938,7 @@ bool emberAfAccountLoginClusterGetSetupPINResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "GetSetupPINResponse:"); ChipLogProgress(Zcl, " setupPIN: %s", setupPIN); - GET_RESPONSE_CALLBACKS("AccountLoginClusterGetSetupPINResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("AccountLoginClusterGetSetupPINResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -907,7 +952,7 @@ bool emberAfApplicationLauncherClusterLaunchAppResponseCallback(chip::app::Comma LogStatus(status); ChipLogProgress(Zcl, " data: %s", data); - GET_RESPONSE_CALLBACKS("ApplicationLauncherClusterLaunchAppResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ApplicationLauncherClusterLaunchAppResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -930,7 +975,7 @@ bool emberAfContentLaunchClusterLaunchContentResponseCallback(chip::app::Command ChipLogProgress(Zcl, " data: %s", data); ChipLogProgress(Zcl, " contentLaunchStatus: %" PRIu8 "", contentLaunchStatus); - GET_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchContentResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchContentResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -945,7 +990,7 @@ bool emberAfContentLaunchClusterLaunchURLResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, " data: %s", data); ChipLogProgress(Zcl, " contentLaunchStatus: %" PRIu8 "", contentLaunchStatus); - GET_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchURLResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ContentLaunchClusterLaunchURLResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -958,7 +1003,7 @@ bool emberAfDoorLockClusterClearAllPinsResponseCallback(chip::app::Command * com ChipLogProgress(Zcl, "ClearAllPinsResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearAllPinsResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearAllPinsResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -979,7 +1024,7 @@ bool emberAfDoorLockClusterClearAllRfidsResponseCallback(chip::app::Command * co ChipLogProgress(Zcl, "ClearAllRfidsResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearAllRfidsResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearAllRfidsResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1000,7 +1045,7 @@ bool emberAfDoorLockClusterClearHolidayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearHolidayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1021,7 +1066,7 @@ bool emberAfDoorLockClusterClearPinResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, "ClearPinResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearPinResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1042,7 +1087,7 @@ bool emberAfDoorLockClusterClearRfidResponseCallback(chip::app::Command * comman ChipLogProgress(Zcl, "ClearRfidResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearRfidResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1063,7 +1108,7 @@ bool emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearWeekdayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1084,7 +1129,7 @@ bool emberAfDoorLockClusterClearYeardayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearYeardayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1111,7 +1156,7 @@ bool emberAfDoorLockClusterGetHolidayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " localEndTime: %" PRIu32 "", localEndTime); ChipLogProgress(Zcl, " operatingModeDuringHoliday: %" PRIu8 "", operatingModeDuringHoliday); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1140,7 +1185,7 @@ bool emberAfDoorLockClusterGetLogRecordResponseCallback(chip::app::Command * com ChipLogProgress(Zcl, " userId: %" PRIu16 "", userId); ChipLogProgress(Zcl, " pin: %s", pin); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetLogRecordResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetLogRecordResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1157,7 +1202,7 @@ bool emberAfDoorLockClusterGetPinResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); ChipLogProgress(Zcl, " pin: %s", pin); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetPinResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1174,7 +1219,7 @@ bool emberAfDoorLockClusterGetRfidResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); ChipLogProgress(Zcl, " rfid: %s", rfid); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetRfidResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1188,7 +1233,7 @@ bool emberAfDoorLockClusterGetUserTypeResponseCallback(chip::app::Command * comm ChipLogProgress(Zcl, " userId: %" PRIu16 "", userId); ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetUserTypeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetUserTypeResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1210,7 +1255,7 @@ bool emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " endHour: %" PRIu8 "", endHour); ChipLogProgress(Zcl, " endMinute: %" PRIu8 "", endMinute); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1236,7 +1281,7 @@ bool emberAfDoorLockClusterGetYeardayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " localStartTime: %" PRIu32 "", localStartTime); ChipLogProgress(Zcl, " localEndTime: %" PRIu32 "", localEndTime); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1257,7 +1302,7 @@ bool emberAfDoorLockClusterLockDoorResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, "LockDoorResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterLockDoorResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterLockDoorResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1278,7 +1323,7 @@ bool emberAfDoorLockClusterSetHolidayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetHolidayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1299,7 +1344,7 @@ bool emberAfDoorLockClusterSetPinResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, "SetPinResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetPinResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1320,7 +1365,7 @@ bool emberAfDoorLockClusterSetRfidResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, "SetRfidResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetRfidResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1341,7 +1386,7 @@ bool emberAfDoorLockClusterSetUserTypeResponseCallback(chip::app::Command * comm ChipLogProgress(Zcl, "SetUserTypeResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetUserTypeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetUserTypeResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1362,7 +1407,7 @@ bool emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetWeekdayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1383,7 +1428,7 @@ bool emberAfDoorLockClusterSetYeardayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetYeardayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1404,7 +1449,7 @@ bool emberAfDoorLockClusterUnlockDoorResponseCallback(chip::app::Command * comma ChipLogProgress(Zcl, "UnlockDoorResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterUnlockDoorResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterUnlockDoorResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1425,7 +1470,7 @@ bool emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(chip::app::Command ChipLogProgress(Zcl, "UnlockWithTimeoutResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterUnlockWithTimeoutResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterUnlockWithTimeoutResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1448,7 +1493,7 @@ bool emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(chip::app::Co ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterArmFailSafeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterArmFailSafeResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1463,7 +1508,7 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(chi ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterCommissioningCompleteResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterCommissioningCompleteResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1478,7 +1523,7 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(chip: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterSetRegulatoryConfigResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterSetRegulatoryConfigResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1492,7 +1537,7 @@ bool emberAfGroupsClusterAddGroupResponseCallback(chip::app::Command * commandOb LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("GroupsClusterAddGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterAddGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1516,7 +1561,7 @@ bool emberAfGroupsClusterGetGroupMembershipResponseCallback(chip::app::Command * ChipLogProgress(Zcl, " groupCount: %" PRIu8 "", groupCount); ChipLogProgress(Zcl, " groupList: %p", groupList); - GET_RESPONSE_CALLBACKS("GroupsClusterGetGroupMembershipResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterGetGroupMembershipResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1530,7 +1575,7 @@ bool emberAfGroupsClusterRemoveGroupResponseCallback(chip::app::Command * comman LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("GroupsClusterRemoveGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterRemoveGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1554,7 +1599,7 @@ bool emberAfGroupsClusterViewGroupResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " groupName: %s", groupName); - GET_RESPONSE_CALLBACKS("GroupsClusterViewGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterViewGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1575,7 +1620,7 @@ bool emberAfIdentifyClusterIdentifyQueryResponseCallback(chip::app::Command * co ChipLogProgress(Zcl, "IdentifyQueryResponse:"); ChipLogProgress(Zcl, " timeout: %" PRIu16 "", timeout); - GET_RESPONSE_CALLBACKS("IdentifyClusterIdentifyQueryResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("IdentifyClusterIdentifyQueryResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1588,7 +1633,7 @@ bool emberAfKeypadInputClusterSendKeyResponseCallback(chip::app::Command * comma ChipLogProgress(Zcl, "SendKeyResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("KeypadInputClusterSendKeyResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("KeypadInputClusterSendKeyResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1609,7 +1654,7 @@ bool emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(chip::app::Comm ChipLogProgress(Zcl, "MediaFastForwardResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaFastForwardResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaFastForwardResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1622,7 +1667,7 @@ bool emberAfMediaPlaybackClusterMediaNextResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, "MediaNextResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaNextResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaNextResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1635,7 +1680,7 @@ bool emberAfMediaPlaybackClusterMediaPauseResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "MediaPauseResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPauseResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPauseResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1648,7 +1693,7 @@ bool emberAfMediaPlaybackClusterMediaPlayResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, "MediaPlayResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPlayResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPlayResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1661,7 +1706,7 @@ bool emberAfMediaPlaybackClusterMediaPreviousResponseCallback(chip::app::Command ChipLogProgress(Zcl, "MediaPreviousResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPreviousResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaPreviousResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1674,7 +1719,7 @@ bool emberAfMediaPlaybackClusterMediaRewindResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "MediaRewindResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaRewindResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaRewindResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1687,7 +1732,7 @@ bool emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(chip::app::Com ChipLogProgress(Zcl, "MediaSkipBackwardResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipBackwardResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipBackwardResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1700,7 +1745,7 @@ bool emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(chip::app::Comm ChipLogProgress(Zcl, "MediaSkipForwardResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipForwardResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipForwardResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1713,7 +1758,7 @@ bool emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(chip::app::Command ChipLogProgress(Zcl, "MediaSkipSeekResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipSeekResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaSkipSeekResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1726,7 +1771,7 @@ bool emberAfMediaPlaybackClusterMediaStartOverResponseCallback(chip::app::Comman ChipLogProgress(Zcl, "MediaStartOverResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStartOverResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStartOverResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1739,7 +1784,7 @@ bool emberAfMediaPlaybackClusterMediaStopResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, "MediaStopResponse:"); ChipLogProgress(Zcl, " mediaPlaybackStatus: %" PRIu8 "", mediaPlaybackStatus); - GET_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStopResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("MediaPlaybackClusterMediaStopResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1754,7 +1799,7 @@ bool emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(chip::ap ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddThreadNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddThreadNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1769,7 +1814,7 @@ bool emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(chip::app: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddWiFiNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddWiFiNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1784,7 +1829,7 @@ bool emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(chip::app: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterDisableNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterDisableNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1799,7 +1844,7 @@ bool emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(chip::app:: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterEnableNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterEnableNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1814,7 +1859,7 @@ bool emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(chip::app:: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterRemoveNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterRemoveNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1833,7 +1878,7 @@ bool emberAfNetworkCommissioningClusterScanNetworksResponseCallback( ChipLogProgress(Zcl, " wifiScanResults: %p", wifiScanResults); ChipLogProgress(Zcl, " threadScanResults: %p", threadScanResults); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterScanNetworksResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterScanNetworksResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1848,7 +1893,7 @@ bool emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(chip: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateThreadNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateThreadNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1863,7 +1908,7 @@ bool emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(chip::a ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateWiFiNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateWiFiNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1885,7 +1930,7 @@ bool emberAfOperationalCredentialsClusterOpCSRResponseCallback(chip::app::Comman ChipLogProgress(Zcl, " VendorReserved3: %s", VendorReserved3); ChipLogProgress(Zcl, " Signature: %s", Signature); - GET_RESPONSE_CALLBACKS("OperationalCredentialsClusterOpCSRResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("OperationalCredentialsClusterOpCSRResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1901,7 +1946,7 @@ bool emberAfOperationalCredentialsClusterOpCertResponseCallback(chip::app::Comma ChipLogProgress(Zcl, " FabricIndex: %" PRIu64 "", FabricIndex); ChipLogProgress(Zcl, " DebugText: %s", DebugText); - GET_RESPONSE_CALLBACKS("OperationalCredentialsClusterOpCertResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("OperationalCredentialsClusterOpCertResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1914,7 +1959,7 @@ bool emberAfOperationalCredentialsClusterSetFabricResponseCallback(chip::app::Co ChipLogProgress(Zcl, "SetFabricResponse:"); ChipLogProgress(Zcl, " FabricId: %" PRIu64 "", FabricId); - GET_RESPONSE_CALLBACKS("OperationalCredentialsClusterSetFabricResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("OperationalCredentialsClusterSetFabricResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1930,7 +1975,7 @@ bool emberAfScenesClusterAddSceneResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterAddSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterAddSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1957,7 +2002,7 @@ bool emberAfScenesClusterGetSceneMembershipResponseCallback(chip::app::Command * ChipLogProgress(Zcl, " sceneCount: %" PRIu8 "", sceneCount); ChipLogProgress(Zcl, " sceneList: %p", sceneList); - GET_RESPONSE_CALLBACKS("ScenesClusterGetSceneMembershipResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterGetSceneMembershipResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1979,7 +2024,7 @@ bool emberAfScenesClusterRemoveAllScenesResponseCallback(chip::app::Command * co LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("ScenesClusterRemoveAllScenesResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterRemoveAllScenesResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2003,7 +2048,7 @@ bool emberAfScenesClusterRemoveSceneResponseCallback(chip::app::Command * comman ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterRemoveSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterRemoveSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2027,7 +2072,7 @@ bool emberAfScenesClusterStoreSceneResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterStoreSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterStoreSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2055,7 +2100,7 @@ bool emberAfScenesClusterViewSceneResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " sceneName: %s", sceneName); ChipLogProgress(Zcl, " extensionFieldSets: %p", extensionFieldSets); - GET_RESPONSE_CALLBACKS("ScenesClusterViewSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterViewSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2079,7 +2124,7 @@ bool emberAfTvChannelClusterChangeChannelResponseCallback(chip::app::Command * c ChipLogProgress(Zcl, " ChannelMatch: %p", ChannelMatch); ChipLogProgress(Zcl, " ErrorType: %" PRIu8 "", ErrorType); - GET_RESPONSE_CALLBACKS("TvChannelClusterChangeChannelResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("TvChannelClusterChangeChannelResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -2093,7 +2138,7 @@ bool emberAfTargetNavigatorClusterNavigateTargetResponseCallback(chip::app::Comm LogStatus(status); ChipLogProgress(Zcl, " data: %s", data); - GET_RESPONSE_CALLBACKS("TargetNavigatorClusterNavigateTargetResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("TargetNavigatorClusterNavigateTargetResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -2114,7 +2159,7 @@ bool emberAfTestClusterClusterTestSpecificResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "TestSpecificResponse:"); ChipLogProgress(Zcl, " returnValue: %" PRIu8 "", returnValue); - GET_RESPONSE_CALLBACKS("TestClusterClusterTestSpecificResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("TestClusterClusterTestSpecificResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -2352,4 +2397,3 @@ bool emberAfReportAttributesCallback(ClusterId clusterId, uint8_t * message, uin return true; } -} diff --git a/src/controller/python/gen/CHIPClientCallbacks.h b/src/controller/python/gen/CHIPClientCallbacks.h index c6a055e9bb5de0..5b9c7dd1d3e63d 100644 --- a/src/controller/python/gen/CHIPClientCallbacks.h +++ b/src/controller/python/gen/CHIPClientCallbacks.h @@ -19,10 +19,17 @@ #pragma once +#include +#include #include #include #include +// Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus +// instead of IM status code. +// #6308 should handle IM error code on the application side, either modify this function or remove this. +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status); + // Global Response Callbacks typedef void (*DefaultSuccessCallback)(void * context); typedef void (*DefaultFailureCallback)(void * context, uint8_t status); diff --git a/src/controller/python/gen/CHIPClusters.cpp b/src/controller/python/gen/CHIPClusters.cpp index cb8040b84608e1..a0b4dd08d3e86a 100644 --- a/src/controller/python/gen/CHIPClusters.cpp +++ b/src/controller/python/gen/CHIPClusters.cpp @@ -34,10 +34,7 @@ namespace Controller { CHIP_ERROR AccountLoginCluster::GetSetupPIN(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan tempAccountIdentifier) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetSetupPINCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -52,22 +49,16 @@ CHIP_ERROR AccountLoginCluster::GetSetupPIN(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeAccountLoginClusterGetSetupPINCommand(seqNum, mEndpoint, tempAccountIdentifier); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR AccountLoginCluster::Login(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan tempAccountIdentifier, chip::ByteSpan setupPIN) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLoginCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -84,13 +75,10 @@ CHIP_ERROR AccountLoginCluster::Login(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeAccountLoginClusterLoginCommand(seqNum, mEndpoint, tempAccountIdentifier, setupPIN); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // AccountLogin Cluster Attributes @@ -186,10 +174,7 @@ CHIP_ERROR ApplicationBasicCluster::ReadAttributeClusterRevision(Callback::Cance CHIP_ERROR ApplicationLauncherCluster::LaunchApp(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan data, uint16_t catalogVendorId, chip::ByteSpan applicationId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLaunchAppCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -208,13 +193,10 @@ CHIP_ERROR ApplicationLauncherCluster::LaunchApp(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeApplicationLauncherClusterLaunchAppCommand(seqNum, mEndpoint, data, catalogVendorId, applicationId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ApplicationLauncher Cluster Attributes @@ -246,10 +228,7 @@ CHIP_ERROR ApplicationLauncherCluster::ReadAttributeClusterRevision(Callback::Ca CHIP_ERROR AudioOutputCluster::RenameOutput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index, chip::ByteSpan name) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRenameOutputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -266,21 +245,16 @@ CHIP_ERROR AudioOutputCluster::RenameOutput(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeAudioOutputClusterRenameOutputCommand(seqNum, mEndpoint, index, name); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR AudioOutputCluster::SelectOutput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSelectOutputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -295,12 +269,10 @@ CHIP_ERROR AudioOutputCluster::SelectOutput(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeAudioOutputClusterSelectOutputCommand(seqNum, mEndpoint, index); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // AudioOutput Cluster Attributes @@ -331,10 +303,7 @@ CHIP_ERROR AudioOutputCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentOpen) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBarrierControlGoToPercentCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -349,22 +318,16 @@ CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBarrierControlClusterBarrierControlGoToPercentCommand(seqNum, mEndpoint, percentOpen); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBarrierControlStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -376,12 +339,10 @@ CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBarrierControlClusterBarrierControlStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // BarrierControl Cluster Attributes @@ -435,10 +396,7 @@ CHIP_ERROR BarrierControlCluster::ReadAttributeClusterRevision(Callback::Cancela // Basic Cluster Commands CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMfgSpecificPingCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -450,12 +408,10 @@ CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBasicClusterMfgSpecificPingCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Basic Cluster Attributes @@ -630,10 +586,7 @@ CHIP_ERROR BasicCluster::ReadAttributeClusterRevision(Callback::Cancelable * onS CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -654,23 +607,17 @@ CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterBindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnbindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -691,13 +638,10 @@ CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterUnbindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Binding Cluster Attributes @@ -719,10 +663,7 @@ CHIP_ERROR BindingCluster::ReadAttributeClusterRevision(Callback::Cancelable * o CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t rateX, int16_t rateY, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -743,13 +684,10 @@ CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveColorCommand(seqNum, mEndpoint, rateX, rateY, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -757,10 +695,7 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -785,22 +720,16 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveColorTemperatureCommand( - seqNum, mEndpoint, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -821,22 +750,16 @@ CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveHueCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -857,23 +780,17 @@ CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveSaturationCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorX, uint16_t colorY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -896,23 +813,17 @@ CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorCommand( - seqNum, mEndpoint, colorX, colorY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorTemperature, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -933,23 +844,17 @@ CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorTemperatureCommand( - seqNum, mEndpoint, colorTemperature, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t direction, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -972,23 +877,17 @@ CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveToHueCommand(seqNum, mEndpoint, hue, direction, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToHueAndSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1011,23 +910,17 @@ CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToHueAndSaturationCommand( - seqNum, mEndpoint, hue, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1048,23 +941,17 @@ CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToSaturationCommand( - seqNum, mEndpoint, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t stepX, int16_t stepY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1087,13 +974,10 @@ CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStepColorCommand(seqNum, mEndpoint, stepX, stepY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -1101,10 +985,7 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu uint16_t transitionTime, uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1131,24 +1012,17 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepColorTemperatureCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, - optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1171,23 +1045,17 @@ CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepHueCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1210,22 +1078,16 @@ CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepSaturationCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopMoveStepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1242,13 +1104,10 @@ CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStopMoveStepCommand(seqNum, mEndpoint, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ColorControl Cluster Attributes @@ -1858,10 +1717,7 @@ CHIP_ERROR ColorControlCluster::ReadAttributeClusterRevision(Callback::Cancelabl CHIP_ERROR ContentLaunchCluster::LaunchContent(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t autoPlay, chip::ByteSpan data) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLaunchContentCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1878,21 +1734,16 @@ CHIP_ERROR ContentLaunchCluster::LaunchContent(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeContentLaunchClusterLaunchContentCommand(seqNum, mEndpoint, autoPlay, data); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ContentLaunchCluster::LaunchURL(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan contentURL, chip::ByteSpan displayString) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLaunchURLCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1909,13 +1760,10 @@ CHIP_ERROR ContentLaunchCluster::LaunchURL(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeContentLaunchClusterLaunchURLCommand(seqNum, mEndpoint, contentURL, displayString); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ContentLaunch Cluster Attributes @@ -2001,10 +1849,7 @@ CHIP_ERROR DescriptorCluster::ReadAttributeClusterRevision(Callback::Cancelable // DoorLock Cluster Commands CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearAllPinsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2016,20 +1861,15 @@ CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllPinsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearAllRfidsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2041,21 +1881,16 @@ CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllRfidsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2070,21 +1905,16 @@ CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2099,21 +1929,16 @@ CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2128,21 +1953,16 @@ CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2159,22 +1979,16 @@ CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2191,22 +2005,16 @@ CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2221,21 +2029,16 @@ CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t logIndex) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetLogRecordCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2250,21 +2053,16 @@ CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetLogRecordCommand(seqNum, mEndpoint, logIndex); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2279,21 +2077,16 @@ CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2308,21 +2101,16 @@ CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetUserTypeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2337,21 +2125,16 @@ CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetUserTypeCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2368,22 +2151,16 @@ CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2400,22 +2177,16 @@ CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLockDoorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2430,22 +2201,17 @@ CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterLockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint32_t localStartTime, uint32_t localEndTime, uint8_t operatingModeDuringHoliday) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2466,22 +2232,16 @@ CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetHolidayScheduleCommand( - seqNum, mEndpoint, scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2502,22 +2262,16 @@ CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetPinCommand(seqNum, mEndpoint, userId, userStatus, userType, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan id) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2538,22 +2292,16 @@ CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetRfidCommand(seqNum, mEndpoint, userId, userStatus, userType, id); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userType) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetUserTypeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2570,22 +2318,17 @@ CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetUserTypeCommand(seqNum, mEndpoint, userId, userType); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint8_t daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2612,22 +2355,16 @@ CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetWeekdayScheduleCommand( - seqNum, mEndpoint, scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint32_t localStartTime, uint32_t localEndTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2648,22 +2385,16 @@ CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId, localStartTime, localEndTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnlockDoorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2678,21 +2409,16 @@ CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterUnlockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t timeoutInSeconds, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnlockWithTimeoutCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2709,13 +2435,10 @@ CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterUnlockWithTimeoutCommand(seqNum, mEndpoint, timeoutInSeconds, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // DoorLock Cluster Attributes @@ -2777,10 +2500,7 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc Callback::Cancelable * onFailureCallback, uint16_t expiryLengthSeconds, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kArmFailSafeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2799,22 +2519,16 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGeneralCommissioningClusterArmFailSafeCommand(seqNum, mEndpoint, expiryLengthSeconds, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kCommissioningCompleteCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2826,22 +2540,17 @@ CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGeneralCommissioningClusterCommissioningCompleteCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t location, chip::ByteSpan countryCode, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetRegulatoryConfigCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2862,13 +2571,10 @@ CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGeneralCommissioningClusterSetRegulatoryConfigCommand( - seqNum, mEndpoint, location, countryCode, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // GeneralCommissioning Cluster Attributes @@ -2948,10 +2654,7 @@ CHIP_ERROR GroupKeyManagementCluster::ReadAttributeClusterRevision(Callback::Can CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2968,21 +2671,16 @@ CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterAddGroupCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddGroupIfIdentifyingCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2999,22 +2697,16 @@ CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterAddGroupIfIdentifyingCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t groupCount, uint16_t groupList) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetGroupMembershipCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3031,21 +2723,15 @@ CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterGetGroupMembershipCommand(seqNum, mEndpoint, groupCount, groupList); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllGroupsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3057,21 +2743,16 @@ CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveAllGroupsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3086,21 +2767,16 @@ CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kViewGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3115,12 +2791,10 @@ CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterViewGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Groups Cluster Attributes @@ -3150,10 +2824,7 @@ CHIP_ERROR GroupsCluster::ReadAttributeClusterRevision(Callback::Cancelable * on CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t identifyTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3168,20 +2839,15 @@ CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyCommand(seqNum, mEndpoint, identifyTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyQueryCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3193,12 +2859,10 @@ CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyQueryCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Identify Cluster Attributes @@ -3236,10 +2900,7 @@ CHIP_ERROR IdentifyCluster::ReadAttributeClusterRevision(Callback::Cancelable * CHIP_ERROR KeypadInputCluster::SendKey(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t keyCode) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSendKeyCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3254,12 +2915,10 @@ CHIP_ERROR KeypadInputCluster::SendKey(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeKeypadInputClusterSendKeyCommand(seqNum, mEndpoint, keyCode); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // KeypadInput Cluster Attributes @@ -3282,10 +2941,7 @@ CHIP_ERROR KeypadInputCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3306,22 +2962,16 @@ CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveCommand(seqNum, mEndpoint, moveMode, rate, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToLevelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3342,23 +2992,17 @@ CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelCommand(seqNum, mEndpoint, level, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToLevelWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3375,22 +3019,16 @@ CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelWithOnOffCommand(seqNum, mEndpoint, level, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3407,22 +3045,17 @@ CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterMoveWithOnOffCommand(seqNum, mEndpoint, moveMode, rate); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3445,22 +3078,16 @@ CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3479,22 +3106,16 @@ CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepWithOnOffCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3511,20 +3132,15 @@ CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopCommand(seqNum, mEndpoint, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3536,12 +3152,10 @@ CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopWithOnOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LevelControl Cluster Attributes @@ -3586,10 +3200,7 @@ CHIP_ERROR LevelControlCluster::ReadAttributeClusterRevision(Callback::Cancelabl // LowPower Cluster Commands CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSleepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3601,12 +3212,10 @@ CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLowPowerClusterSleepCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LowPower Cluster Attributes @@ -3627,10 +3236,7 @@ CHIP_ERROR LowPowerCluster::ReadAttributeClusterRevision(Callback::Cancelable * // MediaInput Cluster Commands CHIP_ERROR MediaInputCluster::HideInputStatus(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kHideInputStatusCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3642,21 +3248,16 @@ CHIP_ERROR MediaInputCluster::HideInputStatus(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterHideInputStatusCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaInputCluster::RenameInput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index, chip::ByteSpan name) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRenameInputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3673,21 +3274,16 @@ CHIP_ERROR MediaInputCluster::RenameInput(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterRenameInputCommand(seqNum, mEndpoint, index, name); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaInputCluster::SelectInput(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t index) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSelectInputCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3702,20 +3298,15 @@ CHIP_ERROR MediaInputCluster::SelectInput(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterSelectInputCommand(seqNum, mEndpoint, index); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaInputCluster::ShowInputStatus(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kShowInputStatusCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3727,12 +3318,10 @@ CHIP_ERROR MediaInputCluster::ShowInputStatus(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaInputClusterShowInputStatusCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // MediaInput Cluster Attributes @@ -3762,10 +3351,7 @@ CHIP_ERROR MediaInputCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR MediaPlaybackCluster::MediaFastForward(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaFastForwardCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3777,20 +3363,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaFastForward(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaFastForwardCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaNext(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaNextCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3802,20 +3383,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaNext(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaNextCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaPause(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaPauseCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3827,20 +3403,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaPause(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaPauseCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaPlay(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaPlayCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3852,20 +3423,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaPlay(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaPlayCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaPrevious(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaPreviousCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3877,20 +3443,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaPrevious(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaPreviousCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaRewind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaRewindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3902,21 +3463,16 @@ CHIP_ERROR MediaPlaybackCluster::MediaRewind(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaRewindCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaSkipBackward(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint64_t deltaPositionMilliseconds) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaSkipBackwardCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3931,22 +3487,16 @@ CHIP_ERROR MediaPlaybackCluster::MediaSkipBackward(Callback::Cancelable * onSucc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeMediaPlaybackClusterMediaSkipBackwardCommand(seqNum, mEndpoint, deltaPositionMilliseconds); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaSkipForward(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint64_t deltaPositionMilliseconds) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaSkipForwardCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3961,22 +3511,16 @@ CHIP_ERROR MediaPlaybackCluster::MediaSkipForward(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeMediaPlaybackClusterMediaSkipForwardCommand(seqNum, mEndpoint, deltaPositionMilliseconds); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaSkipSeek(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint64_t position) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaSkipSeekCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3991,20 +3535,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaSkipSeek(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaSkipSeekCommand(seqNum, mEndpoint, position); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaStartOver(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaStartOverCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4016,20 +3555,15 @@ CHIP_ERROR MediaPlaybackCluster::MediaStartOver(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaStartOverCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR MediaPlaybackCluster::MediaStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMediaStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4041,12 +3575,10 @@ CHIP_ERROR MediaPlaybackCluster::MediaStop(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeMediaPlaybackClusterMediaStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // MediaPlayback Cluster Attributes @@ -4070,10 +3602,7 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * Callback::Cancelable * onFailureCallback, chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddThreadNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4092,23 +3621,17 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddWiFiNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4129,23 +3652,17 @@ CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kDisableNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4164,23 +3681,17 @@ CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterDisableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kEnableNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4199,23 +3710,17 @@ CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterEnableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetLastNetworkCommissioningResultCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4230,23 +3735,17 @@ CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterGetLastNetworkCommissioningResultCommand(seqNum, mEndpoint, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4265,23 +3764,17 @@ CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterRemoveNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kScanNetworksCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4300,13 +3793,10 @@ CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterScanNetworksCommand(seqNum, mEndpoint, ssid, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable * onSuccessCallback, @@ -4314,10 +3804,7 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateThreadNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4336,23 +3823,17 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateWiFiNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4373,13 +3854,10 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // NetworkCommissioning Cluster Attributes @@ -4401,10 +3879,7 @@ CHIP_ERROR NetworkCommissioningCluster::ReadAttributeClusterRevision(Callback::C // OnOff Cluster Commands CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4416,20 +3891,15 @@ CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOnCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4441,20 +3911,15 @@ CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback:: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOnCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kToggleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4466,12 +3931,10 @@ CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterToggleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OnOff Cluster Attributes @@ -4516,10 +3979,7 @@ CHIP_ERROR OperationalCredentialsCluster::AddOpCert(Callback::Cancelable * onSuc chip::ByteSpan iCACertificate, chip::ByteSpan iPKValue, chip::NodeId caseAdminNode, uint16_t adminVendorId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddOpCertCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4542,22 +4002,16 @@ CHIP_ERROR OperationalCredentialsCluster::AddOpCert(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterAddOpCertCommand( - seqNum, mEndpoint, noc, iCACertificate, iPKValue, caseAdminNode, adminVendorId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::OpCSRRequest(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan cSRNonce) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOpCSRRequestCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4572,21 +4026,16 @@ CHIP_ERROR OperationalCredentialsCluster::OpCSRRequest(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterOpCSRRequestCommand(seqNum, mEndpoint, cSRNonce); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::RemoveAllFabrics(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllFabricsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4598,22 +4047,17 @@ CHIP_ERROR OperationalCredentialsCluster::RemoveAllFabrics(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterRemoveAllFabricsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::RemoveFabric(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::FabricId fabricId, chip::NodeId nodeId, uint16_t vendorId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveFabricCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4632,22 +4076,16 @@ CHIP_ERROR OperationalCredentialsCluster::RemoveFabric(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeOperationalCredentialsClusterRemoveFabricCommand(seqNum, mEndpoint, fabricId, nodeId, vendorId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::SetFabric(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t vendorId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetFabricCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4662,21 +4100,16 @@ CHIP_ERROR OperationalCredentialsCluster::SetFabric(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterSetFabricCommand(seqNum, mEndpoint, vendorId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan label) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateFabricLabelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4691,13 +4124,10 @@ CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeOperationalCredentialsClusterUpdateFabricLabelCommand(seqNum, mEndpoint, label); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OperationalCredentials Cluster Attributes @@ -4831,10 +4261,7 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, chip::ByteSpan sceneName, chip::ClusterId clusterId, uint8_t length, uint8_t value) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4861,22 +4288,16 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterAddSceneCommand( - seqNum, mEndpoint, groupId, sceneId, transitionTime, sceneName, clusterId, length, value); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetSceneMembershipCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4891,21 +4312,16 @@ CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterGetSceneMembershipCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRecallSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4924,22 +4340,16 @@ CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeScenesClusterRecallSceneCommand(seqNum, mEndpoint, groupId, sceneId, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllScenesCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4954,21 +4364,16 @@ CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveAllScenesCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4985,21 +4390,16 @@ CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStoreSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5016,21 +4416,16 @@ CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterStoreSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kViewSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5047,12 +4442,10 @@ CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterViewSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Scenes Cluster Attributes @@ -5161,10 +4554,7 @@ CHIP_ERROR SwitchCluster::ReadAttributeClusterRevision(Callback::Cancelable * on CHIP_ERROR TvChannelCluster::ChangeChannel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan match) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kChangeChannelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5179,22 +4569,17 @@ CHIP_ERROR TvChannelCluster::ChangeChannel(Callback::Cancelable * onSuccessCallb ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTvChannelClusterChangeChannelCommand(seqNum, mEndpoint, match); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TvChannelCluster::ChangeChannelByNumber(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t majorNumber, uint16_t minorNumber) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kChangeChannelByNumberCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5211,22 +4596,16 @@ CHIP_ERROR TvChannelCluster::ChangeChannelByNumber(Callback::Cancelable * onSucc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeTvChannelClusterChangeChannelByNumberCommand(seqNum, mEndpoint, majorNumber, minorNumber); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TvChannelCluster::SkipChannel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t count) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSkipChannelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5241,12 +4620,10 @@ CHIP_ERROR TvChannelCluster::SkipChannel(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTvChannelClusterSkipChannelCommand(seqNum, mEndpoint, count); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // TvChannel Cluster Attributes @@ -5292,10 +4669,7 @@ CHIP_ERROR TvChannelCluster::ReadAttributeClusterRevision(Callback::Cancelable * CHIP_ERROR TargetNavigatorCluster::NavigateTarget(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t target, chip::ByteSpan data) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kNavigateTargetCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5312,12 +4686,10 @@ CHIP_ERROR TargetNavigatorCluster::NavigateTarget(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTargetNavigatorClusterNavigateTargetCommand(seqNum, mEndpoint, target, data); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // TargetNavigator Cluster Attributes @@ -5404,10 +4776,7 @@ CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeClusterRevision(Callback: // TestCluster Cluster Commands CHIP_ERROR TestClusterCluster::Test(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5419,20 +4788,15 @@ CHIP_ERROR TestClusterCluster::Test(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TestClusterCluster::TestNotHandled(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestNotHandledCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5444,20 +4808,15 @@ CHIP_ERROR TestClusterCluster::TestNotHandled(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestNotHandledCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TestClusterCluster::TestSpecific(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestSpecificCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5469,12 +4828,10 @@ CHIP_ERROR TestClusterCluster::TestSpecific(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestSpecificCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // TestCluster Cluster Attributes @@ -5761,10 +5118,7 @@ CHIP_ERROR TestClusterCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR ThermostatCluster::ClearWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5776,20 +5130,15 @@ CHIP_ERROR ThermostatCluster::ClearWeeklySchedule(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterClearWeeklyScheduleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::GetRelayStatusLog(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetRelayStatusLogCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5801,21 +5150,16 @@ CHIP_ERROR ThermostatCluster::GetRelayStatusLog(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterGetRelayStatusLogCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::GetWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t daysToReturn, uint8_t modeToReturn) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5832,23 +5176,17 @@ CHIP_ERROR ThermostatCluster::GetWeeklySchedule(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeThermostatClusterGetWeeklyScheduleCommand(seqNum, mEndpoint, daysToReturn, modeToReturn); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::SetWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t numberOfTransitionsForSequence, uint8_t dayOfWeekForSequence, uint8_t modeForSequence, uint8_t payload) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5869,22 +5207,16 @@ CHIP_ERROR ThermostatCluster::SetWeeklySchedule(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterSetWeeklyScheduleCommand( - seqNum, mEndpoint, numberOfTransitionsForSequence, dayOfWeekForSequence, modeForSequence, payload); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::SetpointRaiseLower(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t mode, int8_t amount) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetpointRaiseLowerCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -5901,12 +5233,10 @@ CHIP_ERROR ThermostatCluster::SetpointRaiseLower(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterSetpointRaiseLowerCommand(seqNum, mEndpoint, mode, amount); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Thermostat Cluster Attributes @@ -6042,10 +5372,7 @@ CHIP_ERROR WakeOnLanCluster::ReadAttributeClusterRevision(Callback::Cancelable * CHIP_ERROR WindowCoveringCluster::WindowCoveringDownClose(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kWindowCoveringDownCloseCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -6057,22 +5384,17 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringDownClose(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeWindowCoveringClusterWindowCoveringDownCloseCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftPercentage(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentageLiftValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kWindowCoveringGoToLiftPercentageCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -6087,22 +5409,16 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftPercentage(Callback::Can ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToLiftPercentageCommand(seqNum, mEndpoint, percentageLiftValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftValue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t liftValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kWindowCoveringGoToLiftValueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -6117,23 +5433,17 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftValue(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToLiftValueCommand(seqNum, mEndpoint, liftValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltPercentage(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentageTiltValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kWindowCoveringGoToTiltPercentageCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -6148,22 +5458,16 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltPercentage(Callback::Can ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToTiltPercentageCommand(seqNum, mEndpoint, percentageTiltValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltValue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t tiltValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kWindowCoveringGoToTiltValueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -6178,22 +5482,16 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltValue(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToTiltValueCommand(seqNum, mEndpoint, tiltValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kWindowCoveringStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -6205,21 +5503,16 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringStop(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeWindowCoveringClusterWindowCoveringStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringUpOpen(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kWindowCoveringUpOpenCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -6231,12 +5524,10 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringUpOpen(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeWindowCoveringClusterWindowCoveringUpOpenCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // WindowCovering Cluster Attributes diff --git a/src/controller/python/gen/IMClusterCommandHandler.cpp b/src/controller/python/gen/IMClusterCommandHandler.cpp index 34c39743e30986..451bb64154f877 100644 --- a/src/controller/python/gen/IMClusterCommandHandler.cpp +++ b/src/controller/python/gen/IMClusterCommandHandler.cpp @@ -43,47 +43,62 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * setupPIN; - bool setupPINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (setupPINExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(setupPIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - setupPINExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -93,36 +108,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfAccountLoginClusterGetSetupPINResponseCallback(apCommandObj, const_cast(setupPIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfAccountLoginClusterGetSetupPINResponseCallback(apCommandObj, const_cast(setupPIN)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ACCOUNT_LOGIN_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace AccountLogin @@ -131,63 +151,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; const uint8_t * data; - bool dataExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (dataExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) - { - dataExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -197,36 +220,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfApplicationLauncherClusterLaunchAppResponseCallback(apCommandObj, status, const_cast(data)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfApplicationLauncherClusterLaunchAppResponseCallback(apCommandObj, status, const_cast(data)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_APPLICATION_LAUNCHER_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ApplicationLauncher @@ -235,63 +264,66 @@ namespace ContentLaunch { 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; const uint8_t * data; - bool dataExists = false; uint8_t contentLaunchStatus; - bool contentLaunchStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (dataExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - dataExists = true; + 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: - if (contentLaunchStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(contentLaunchStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - contentLaunchStatusExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -301,82 +333,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfContentLaunchClusterLaunchContentResponseCallback(apCommandObj, const_cast(data), - contentLaunchStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfContentLaunchClusterLaunchContentResponseCallback(apCommandObj, const_cast(data), + contentLaunchStatus); } break; } case ZCL_LAUNCH_URL_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; const uint8_t * data; - bool dataExists = false; uint8_t contentLaunchStatus; - bool contentLaunchStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (dataExists) + 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; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - dataExists = true; + 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: - if (contentLaunchStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(contentLaunchStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - contentLaunchStatusExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -386,37 +398,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfContentLaunchClusterLaunchURLResponseCallback(apCommandObj, const_cast(data), - contentLaunchStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfContentLaunchClusterLaunchURLResponseCallback(apCommandObj, const_cast(data), + contentLaunchStatus); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_CONTENT_LAUNCH_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ContentLaunch @@ -425,46 +442,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -474,64 +506,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -541,64 +565,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -608,64 +624,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -675,64 +683,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -742,64 +742,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -809,64 +801,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -876,128 +860,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 4: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1007,162 +935,82 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetHolidayScheduleResponseCallback(apCommandObj, scheduleId, status, localStartTime, - localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetHolidayScheduleResponseCallback( + apCommandObj, scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday); } break; } case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint16_t logEntryId; - bool logEntryIdExists = false; uint32_t timestamp; - bool timestampExists = false; uint8_t eventType; - bool eventTypeExists = false; uint8_t source; - bool sourceExists = false; uint8_t eventIdOrAlarmCode; - bool eventIdOrAlarmCodeExists = false; uint16_t userId; - bool userIdExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (logEntryIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(logEntryId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logEntryIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logEntryId); break; case 1: - if (timestampExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timestamp); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timestampExists = true; - validArgumentCount++; - } break; case 2: - if (eventTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventTypeExists = true; - validArgumentCount++; - } break; case 3: - if (sourceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(source); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sourceExists = true; - validArgumentCount++; - } break; case 4: - if (eventIdOrAlarmCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventIdOrAlarmCodeExists = true; - validArgumentCount++; - } break; case 5: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 6: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1172,114 +1020,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetLogRecordResponseCallback(apCommandObj, logEntryId, timestamp, eventType, source, - eventIdOrAlarmCode, userId, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetLogRecordResponseCallback( + apCommandObj, logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast(pin)); } break; } case ZCL_GET_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1289,114 +1093,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType, - const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType, + const_cast(pin)); } break; } case ZCL_GET_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * rfid; - bool rfidExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (rfidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(rfid); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rfidExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1406,81 +1166,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType, - const_cast(rfid)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType, + const_cast(rfid)); } break; } case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1490,176 +1230,84 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType); } break; } case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 8; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[8]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 4: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } break; case 5: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 6: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 7: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1669,129 +1317,73 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, daysMask, - startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 8, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetWeekdayScheduleResponseCallback( + apCommandObj, scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute); } break; } case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 4: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1801,65 +1393,57 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, localStartTime, - localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, + localStartTime, localEndTime); } break; } case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1869,64 +1453,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status); } break; } case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1936,64 +1512,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_SET_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2003,64 +1571,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status); } break; } case ZCL_SET_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2070,64 +1630,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status); } break; } case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2137,64 +1689,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status); } break; } case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2204,64 +1748,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2271,64 +1807,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2338,64 +1866,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status); } break; } case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2405,36 +1925,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -2443,63 +1968,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2509,82 +2037,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2594,82 +2102,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } case ZCL_SET_REGULATORY_CONFIG_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2679,37 +2167,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -2718,62 +2211,65 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2783,97 +2279,65 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t capacity; - bool capacityExists = false; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (capacityExists) + 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; } - TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - capacityExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(capacity); break; case 1: - if (groupCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupCountExists = true; - validArgumentCount++; - } break; case 2: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2883,80 +2347,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList); } break; } case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2966,97 +2410,65 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3066,36 +2478,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast(groupName)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -3104,46 +2522,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t timeout; - bool timeoutExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeout); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3153,36 +2586,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -3191,46 +2629,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3240,36 +2693,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfKeypadInputClusterSendKeyResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfKeypadInputClusterSendKeyResponseCallback(apCommandObj, status); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_KEYPAD_INPUT_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace KeypadInput @@ -3278,46 +2736,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3327,64 +2800,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_NEXT_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3394,64 +2859,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaNextResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaNextResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_PAUSE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3461,64 +2918,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaPauseResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaPauseResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_PLAY_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3528,64 +2977,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaPlayResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaPlayResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_PREVIOUS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3595,64 +3036,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaPreviousResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaPreviousResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_REWIND_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3662,64 +3095,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaRewindResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaRewindResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_SKIP_BACKWARD_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3729,64 +3154,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_SKIP_FORWARD_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3796,64 +3213,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_SKIP_SEEK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3863,64 +3272,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_START_OVER_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3930,64 +3331,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaStartOverResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaStartOverResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } case ZCL_MEDIA_STOP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t mediaPlaybackStatus; - bool mediaPlaybackStatusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (mediaPlaybackStatusExists) + 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; } - TLVUnpackError = aDataTlv.Get(mediaPlaybackStatus); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - mediaPlaybackStatusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3997,36 +3390,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfMediaPlaybackClusterMediaStopResponseCallback(apCommandObj, mediaPlaybackStatus); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfMediaPlaybackClusterMediaStopResponseCallback(apCommandObj, mediaPlaybackStatus); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_MEDIA_PLAYBACK_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace MediaPlayback @@ -4035,63 +3433,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4101,82 +3502,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4186,82 +3567,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4271,82 +3632,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4356,82 +3697,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4441,116 +3762,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; - bool wifiScanResultsExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; - bool threadScanResultsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - errorCodeExists = true; - validArgumentCount++; - } - break; - case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } - break; - case 2: - if (wifiScanResultsExists) + 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; } - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(wifiScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - wifiScanResultsExists = true; + 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(wifiScanResults)); break; case 3: - if (threadScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(threadScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - threadScanResultsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4560,82 +3837,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksResponseCallback( + wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback( apCommandObj, errorCode, const_cast(debugText), wifiScanResults, threadScanResults); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4645,82 +3902,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4730,37 +3967,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -4769,166 +4011,103 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; chip::ByteSpan CSR; - bool CSRExists = false; uint32_t CSRLen; - bool CSRLenExists = false; chip::ByteSpan CSRNonce; - bool CSRNonceExists = false; chip::ByteSpan VendorReserved1; - bool VendorReserved1Exists = false; chip::ByteSpan VendorReserved2; - bool VendorReserved2Exists = false; chip::ByteSpan VendorReserved3; - bool VendorReserved3Exists = false; chip::ByteSpan Signature; - bool SignatureExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (CSRExists) + 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 { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - CSR = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - CSRExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + CSR = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (CSRLenExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(CSRLen); - if (CHIP_NO_ERROR == TLVUnpackError) - { - CSRLenExists = true; - validArgumentCount++; - } - break; - case 2: - if (CSRNonceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - CSRNonce = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - CSRNonceExists = true; - validArgumentCount++; - } - break; - case 3: - if (VendorReserved1Exists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - VendorReserved1 = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - VendorReserved1Exists = true; - validArgumentCount++; - } - break; - case 4: - if (VendorReserved2Exists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - VendorReserved2 = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - VendorReserved2Exists = true; - validArgumentCount++; - } - break; - case 5: - if (VendorReserved3Exists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - VendorReserved3 = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - VendorReserved3Exists = true; - validArgumentCount++; - } - break; - case 6: - if (SignatureExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - Signature = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - SignatureExists = true; - validArgumentCount++; - } break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + CSRNonce = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 3: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + VendorReserved1 = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + VendorReserved2 = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + VendorReserved3 = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 6: { + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4938,98 +4117,66 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterOpCSRResponseCallback(apCommandObj, CSR, CSRLen, CSRNonce, VendorReserved1, - VendorReserved2, VendorReserved3, Signature); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterOpCSRResponseCallback( + apCommandObj, CSR, CSRLen, CSRNonce, VendorReserved1, VendorReserved2, VendorReserved3, Signature); } break; } case ZCL_OP_CERT_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t StatusCode; - bool StatusCodeExists = false; uint64_t FabricIndex; - bool FabricIndexExists = false; const uint8_t * DebugText; - bool DebugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (StatusCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(StatusCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - StatusCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(StatusCode); break; case 1: - if (FabricIndexExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(FabricIndex); - if (CHIP_NO_ERROR == TLVUnpackError) - { - FabricIndexExists = true; - validArgumentCount++; - } break; case 2: - if (DebugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(DebugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - DebugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5039,65 +4186,57 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterOpCertResponseCallback(apCommandObj, StatusCode, FabricIndex, - const_cast(DebugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterOpCertResponseCallback(apCommandObj, StatusCode, FabricIndex, + const_cast(DebugText)); } break; } case ZCL_SET_FABRIC_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; chip::FabricId FabricId; - bool FabricIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (FabricIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(FabricId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - FabricIdExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5107,37 +4246,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OperationalCredentials @@ -5146,78 +4290,69 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5227,129 +4362,73 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t status; - bool statusExists = false; uint8_t capacity; - bool capacityExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneCount; - bool sceneCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * sceneList; - bool sceneListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) - { - case 0: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } - break; - case 1: - if (capacityExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) - { - capacityExists = true; - validArgumentCount++; - } - break; - case 2: - if (groupIdExists) + { + // 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; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + 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: - if (sceneCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneCountExists = true; - validArgumentCount++; - } break; case 4: - if (sceneListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(sceneList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5359,81 +4438,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId, sceneCount, - sceneList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId, + sceneCount, sceneList); } break; } case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5443,96 +4502,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5542,96 +4569,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5641,146 +4636,78 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 3: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 4: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 5: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5790,37 +4717,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime, - const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime, + const_cast(sceneName), extensionFieldSets); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes @@ -5829,63 +4761,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; /* TYPE WARNING: array array defaults to */ uint8_t * ChannelMatch; - bool ChannelMatchExists = false; uint8_t ErrorType; - bool ErrorTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (ChannelMatchExists) + 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; } - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(ChannelMatch)); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - ChannelMatchExists = true; + 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(ChannelMatch)); break; case 1: - if (ErrorTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(ErrorType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - ErrorTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5895,36 +4830,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTvChannelClusterChangeChannelResponseCallback(apCommandObj, ChannelMatch, ErrorType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTvChannelClusterChangeChannelResponseCallback(apCommandObj, ChannelMatch, ErrorType); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TV_CHANNEL_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TvChannel @@ -5933,63 +4873,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; const uint8_t * data; - bool dataExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (dataExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(data); - if (CHIP_NO_ERROR == TLVUnpackError) - { - dataExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -5999,36 +4942,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTargetNavigatorClusterNavigateTargetResponseCallback(apCommandObj, status, const_cast(data)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfTargetNavigatorClusterNavigateTargetResponseCallback(apCommandObj, status, const_cast(data)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TARGET_NAVIGATOR_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TargetNavigator @@ -6037,46 +4986,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t returnValue; - bool returnValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (returnValueExists) + 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; } - TLVUnpackError = aDataTlv.Get(returnValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - returnValueExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -6086,36 +5050,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TEST_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TestCluster @@ -6132,10 +5101,60 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC 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::ContentLaunch::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_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. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } diff --git a/src/controller/python/gen/callback.h b/src/controller/python/gen/callback.h index caa1cc070807e1..6ded6032c85c3c 100644 --- a/src/controller/python/gen/callback.h +++ b/src/controller/python/gen/callback.h @@ -27,8 +27,6 @@ #include #include -extern "C" { - /** @brief Cluster Init * * This function is called when a specific cluster is initialized. It gives the @@ -3691,4 +3689,3 @@ EmberStatus emberAfInterpanSendMessageCallback(EmberAfInterpanHeader * header, u * */ bool emberAfStartMoveCallback(); -} diff --git a/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.cpp b/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.cpp index 60988152d9a64a..fa9da793c93e01 100644 --- a/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.cpp +++ b/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.cpp @@ -19,6 +19,8 @@ #include "gen/CHIPClientCallbacks.h" +#include + #include "gen/enums.h" #include #include @@ -80,6 +82,28 @@ using namespace ::chip; return true; \ } +#define GET_CLUSTER_RESPONSE_CALLBACKS(name) \ + Callback::Cancelable * onSuccessCallback = nullptr; \ + Callback::Cancelable * onFailureCallback = nullptr; \ + NodeId sourceIdentifier = reinterpret_cast(commandObj); \ + /* #6559: Currently, we only have one commands for the IMInvokeCommands and to a device, so the seqNum is always set to 0. */ \ + CHIP_ERROR err = gCallbacks.GetResponseCallback(sourceIdentifier, 0, &onSuccessCallback, &onFailureCallback); \ + \ + if (CHIP_NO_ERROR != err) \ + { \ + if (onSuccessCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing success callback", name); \ + } \ + \ + if (onFailureCallback == nullptr) \ + { \ + ChipLogDetail(Zcl, "%s: Missing failure callback", name); \ + } \ + \ + return true; \ + } + #define GET_REPORT_CALLBACK(name) \ Callback::Cancelable * onReportCallback = nullptr; \ CHIP_ERROR err = gCallbacks.GetReportCallback(sourceId, endpointId, clusterId, attributeId, &onReportCallback); \ @@ -248,6 +272,29 @@ bool emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, Em return true; } +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status) +{ + ChipLogProgress(Zcl, "DefaultResponse:"); + ChipLogProgress(Zcl, " Transaction: %p", commandObj); + LogStatus(status); + + GET_CLUSTER_RESPONSE_CALLBACKS("emberAfDefaultResponseCallback"); + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onSuccessCallback); + cb->mCall(cb->mContext); + } + else + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, static_cast(status)); + } + + return true; +} + bool emberAfReadAttributesResponseCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) { ChipLogProgress(Zcl, "ReadAttributesResponse:"); @@ -891,7 +938,7 @@ bool emberAfDoorLockClusterClearAllPinsResponseCallback(chip::app::Command * com ChipLogProgress(Zcl, "ClearAllPinsResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearAllPinsResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearAllPinsResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -912,7 +959,7 @@ bool emberAfDoorLockClusterClearAllRfidsResponseCallback(chip::app::Command * co ChipLogProgress(Zcl, "ClearAllRfidsResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearAllRfidsResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearAllRfidsResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -933,7 +980,7 @@ bool emberAfDoorLockClusterClearHolidayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearHolidayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -954,7 +1001,7 @@ bool emberAfDoorLockClusterClearPinResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, "ClearPinResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearPinResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -975,7 +1022,7 @@ bool emberAfDoorLockClusterClearRfidResponseCallback(chip::app::Command * comman ChipLogProgress(Zcl, "ClearRfidResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearRfidResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -996,7 +1043,7 @@ bool emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearWeekdayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1017,7 +1064,7 @@ bool emberAfDoorLockClusterClearYeardayScheduleResponseCallback(chip::app::Comma ChipLogProgress(Zcl, "ClearYeardayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterClearYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterClearYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1044,7 +1091,7 @@ bool emberAfDoorLockClusterGetHolidayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " localEndTime: %" PRIu32 "", localEndTime); ChipLogProgress(Zcl, " operatingModeDuringHoliday: %" PRIu8 "", operatingModeDuringHoliday); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1073,7 +1120,7 @@ bool emberAfDoorLockClusterGetLogRecordResponseCallback(chip::app::Command * com ChipLogProgress(Zcl, " userId: %" PRIu16 "", userId); ChipLogProgress(Zcl, " pin: %s", pin); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetLogRecordResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetLogRecordResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1090,7 +1137,7 @@ bool emberAfDoorLockClusterGetPinResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); ChipLogProgress(Zcl, " pin: %s", pin); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetPinResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1107,7 +1154,7 @@ bool emberAfDoorLockClusterGetRfidResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); ChipLogProgress(Zcl, " rfid: %s", rfid); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetRfidResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1121,7 +1168,7 @@ bool emberAfDoorLockClusterGetUserTypeResponseCallback(chip::app::Command * comm ChipLogProgress(Zcl, " userId: %" PRIu16 "", userId); ChipLogProgress(Zcl, " userType: %" PRIu8 "", userType); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetUserTypeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetUserTypeResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1143,7 +1190,7 @@ bool emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " endHour: %" PRIu8 "", endHour); ChipLogProgress(Zcl, " endMinute: %" PRIu8 "", endMinute); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1169,7 +1216,7 @@ bool emberAfDoorLockClusterGetYeardayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, " localStartTime: %" PRIu32 "", localStartTime); ChipLogProgress(Zcl, " localEndTime: %" PRIu32 "", localEndTime); - GET_RESPONSE_CALLBACKS("DoorLockClusterGetYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterGetYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1190,7 +1237,7 @@ bool emberAfDoorLockClusterLockDoorResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, "LockDoorResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterLockDoorResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterLockDoorResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1211,7 +1258,7 @@ bool emberAfDoorLockClusterSetHolidayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetHolidayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetHolidayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetHolidayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1232,7 +1279,7 @@ bool emberAfDoorLockClusterSetPinResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, "SetPinResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetPinResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetPinResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1253,7 +1300,7 @@ bool emberAfDoorLockClusterSetRfidResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, "SetRfidResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetRfidResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetRfidResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1274,7 +1321,7 @@ bool emberAfDoorLockClusterSetUserTypeResponseCallback(chip::app::Command * comm ChipLogProgress(Zcl, "SetUserTypeResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetUserTypeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetUserTypeResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1295,7 +1342,7 @@ bool emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetWeekdayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetWeekdayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetWeekdayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1316,7 +1363,7 @@ bool emberAfDoorLockClusterSetYeardayScheduleResponseCallback(chip::app::Command ChipLogProgress(Zcl, "SetYeardayScheduleResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterSetYeardayScheduleResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterSetYeardayScheduleResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1337,7 +1384,7 @@ bool emberAfDoorLockClusterUnlockDoorResponseCallback(chip::app::Command * comma ChipLogProgress(Zcl, "UnlockDoorResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterUnlockDoorResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterUnlockDoorResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1358,7 +1405,7 @@ bool emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(chip::app::Command ChipLogProgress(Zcl, "UnlockWithTimeoutResponse:"); LogStatus(status); - GET_RESPONSE_CALLBACKS("DoorLockClusterUnlockWithTimeoutResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("DoorLockClusterUnlockWithTimeoutResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1381,7 +1428,7 @@ bool emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(chip::app::Co ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterArmFailSafeResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterArmFailSafeResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1396,7 +1443,7 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(chi ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterCommissioningCompleteResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterCommissioningCompleteResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1411,7 +1458,7 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(chip: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("GeneralCommissioningClusterSetRegulatoryConfigResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GeneralCommissioningClusterSetRegulatoryConfigResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1425,7 +1472,7 @@ bool emberAfGroupsClusterAddGroupResponseCallback(chip::app::Command * commandOb LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("GroupsClusterAddGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterAddGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1449,7 +1496,7 @@ bool emberAfGroupsClusterGetGroupMembershipResponseCallback(chip::app::Command * ChipLogProgress(Zcl, " groupCount: %" PRIu8 "", groupCount); ChipLogProgress(Zcl, " groupList: %p", groupList); - GET_RESPONSE_CALLBACKS("GroupsClusterGetGroupMembershipResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterGetGroupMembershipResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1463,7 +1510,7 @@ bool emberAfGroupsClusterRemoveGroupResponseCallback(chip::app::Command * comman LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("GroupsClusterRemoveGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterRemoveGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1487,7 +1534,7 @@ bool emberAfGroupsClusterViewGroupResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " groupName: %s", groupName); - GET_RESPONSE_CALLBACKS("GroupsClusterViewGroupResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("GroupsClusterViewGroupResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1508,7 +1555,7 @@ bool emberAfIdentifyClusterIdentifyQueryResponseCallback(chip::app::Command * co ChipLogProgress(Zcl, "IdentifyQueryResponse:"); ChipLogProgress(Zcl, " timeout: %" PRIu16 "", timeout); - GET_RESPONSE_CALLBACKS("IdentifyClusterIdentifyQueryResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("IdentifyClusterIdentifyQueryResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1523,7 +1570,7 @@ bool emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(chip::ap ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddThreadNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddThreadNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1538,7 +1585,7 @@ bool emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(chip::app: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddWiFiNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterAddWiFiNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1553,7 +1600,7 @@ bool emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(chip::app: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterDisableNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterDisableNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1568,7 +1615,7 @@ bool emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(chip::app:: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterEnableNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterEnableNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1583,7 +1630,7 @@ bool emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(chip::app:: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterRemoveNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterRemoveNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1602,7 +1649,7 @@ bool emberAfNetworkCommissioningClusterScanNetworksResponseCallback( ChipLogProgress(Zcl, " wifiScanResults: %p", wifiScanResults); ChipLogProgress(Zcl, " threadScanResults: %p", threadScanResults); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterScanNetworksResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterScanNetworksResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1617,7 +1664,7 @@ bool emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(chip: ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateThreadNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateThreadNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1632,7 +1679,7 @@ bool emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(chip::a ChipLogProgress(Zcl, " errorCode: %" PRIu8 "", errorCode); ChipLogProgress(Zcl, " debugText: %s", debugText); - GET_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateWiFiNetworkResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("NetworkCommissioningClusterUpdateWiFiNetworkResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1645,7 +1692,7 @@ bool emberAfOperationalCredentialsClusterSetFabricResponseCallback(chip::app::Co ChipLogProgress(Zcl, "SetFabricResponse:"); ChipLogProgress(Zcl, " FabricId: %" PRIu64 "", FabricId); - GET_RESPONSE_CALLBACKS("OperationalCredentialsClusterSetFabricResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("OperationalCredentialsClusterSetFabricResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); @@ -1661,7 +1708,7 @@ bool emberAfScenesClusterAddSceneResponseCallback(chip::app::Command * commandOb ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterAddSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterAddSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1688,7 +1735,7 @@ bool emberAfScenesClusterGetSceneMembershipResponseCallback(chip::app::Command * ChipLogProgress(Zcl, " sceneCount: %" PRIu8 "", sceneCount); ChipLogProgress(Zcl, " sceneList: %p", sceneList); - GET_RESPONSE_CALLBACKS("ScenesClusterGetSceneMembershipResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterGetSceneMembershipResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1710,7 +1757,7 @@ bool emberAfScenesClusterRemoveAllScenesResponseCallback(chip::app::Command * co LogStatus(status); ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); - GET_RESPONSE_CALLBACKS("ScenesClusterRemoveAllScenesResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterRemoveAllScenesResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1734,7 +1781,7 @@ bool emberAfScenesClusterRemoveSceneResponseCallback(chip::app::Command * comman ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterRemoveSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterRemoveSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1758,7 +1805,7 @@ bool emberAfScenesClusterStoreSceneResponseCallback(chip::app::Command * command ChipLogProgress(Zcl, " groupId: %" PRIu16 "", groupId); ChipLogProgress(Zcl, " sceneId: %" PRIu8 "", sceneId); - GET_RESPONSE_CALLBACKS("ScenesClusterStoreSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterStoreSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1786,7 +1833,7 @@ bool emberAfScenesClusterViewSceneResponseCallback(chip::app::Command * commandO ChipLogProgress(Zcl, " sceneName: %s", sceneName); ChipLogProgress(Zcl, " extensionFieldSets: %p", extensionFieldSets); - GET_RESPONSE_CALLBACKS("ScenesClusterViewSceneResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("ScenesClusterViewSceneResponseCallback"); if (status != EMBER_ZCL_STATUS_SUCCESS) { @@ -1807,7 +1854,7 @@ bool emberAfTestClusterClusterTestSpecificResponseCallback(chip::app::Command * ChipLogProgress(Zcl, "TestSpecificResponse:"); ChipLogProgress(Zcl, " returnValue: %" PRIu8 "", returnValue); - GET_RESPONSE_CALLBACKS("TestClusterClusterTestSpecificResponseCallback"); + GET_CLUSTER_RESPONSE_CALLBACKS("TestClusterClusterTestSpecificResponseCallback"); Callback::Callback * cb = Callback::Callback::FromCancelable(onSuccessCallback); diff --git a/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.h b/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.h index 5918c99d1bc450..d3f6e6db18a0e5 100644 --- a/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.h +++ b/src/darwin/Framework/CHIP/gen/CHIPClientCallbacks.h @@ -19,10 +19,17 @@ #pragma once +#include +#include #include #include #include +// Note: The IMDefaultResponseCallback is a bridge to the old CallbackMgr before IM is landed, so it still accepts EmberAfStatus +// instead of IM status code. +// #6308 should handle IM error code on the application side, either modify this function or remove this. +bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfStatus status); + // Global Response Callbacks typedef void (*DefaultSuccessCallback)(void * context); typedef void (*DefaultFailureCallback)(void * context, uint8_t status); diff --git a/src/darwin/Framework/CHIP/gen/CHIPClusters.cpp b/src/darwin/Framework/CHIP/gen/CHIPClusters.cpp index a53d9ca5b1a24d..693b53ef7b7f49 100644 --- a/src/darwin/Framework/CHIP/gen/CHIPClusters.cpp +++ b/src/darwin/Framework/CHIP/gen/CHIPClusters.cpp @@ -107,10 +107,7 @@ CHIP_ERROR ApplicationBasicCluster::ReadAttributeClusterRevision(Callback::Cance CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentOpen) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBarrierControlGoToPercentCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -125,22 +122,16 @@ CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBarrierControlClusterBarrierControlGoToPercentCommand(seqNum, mEndpoint, percentOpen); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBarrierControlStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -152,12 +143,10 @@ CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBarrierControlClusterBarrierControlStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // BarrierControl Cluster Attributes @@ -211,10 +200,7 @@ CHIP_ERROR BarrierControlCluster::ReadAttributeClusterRevision(Callback::Cancela // Basic Cluster Commands CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMfgSpecificPingCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -226,12 +212,10 @@ CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBasicClusterMfgSpecificPingCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Basic Cluster Attributes @@ -406,10 +390,7 @@ CHIP_ERROR BasicCluster::ReadAttributeClusterRevision(Callback::Cancelable * onS CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kBindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -430,23 +411,17 @@ CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterBindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnbindCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -467,13 +442,10 @@ CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterUnbindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Binding Cluster Attributes @@ -495,10 +467,7 @@ CHIP_ERROR BindingCluster::ReadAttributeClusterRevision(Callback::Cancelable * o CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t rateX, int16_t rateY, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -519,13 +488,10 @@ CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveColorCommand(seqNum, mEndpoint, rateX, rateY, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -533,10 +499,7 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -561,22 +524,16 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveColorTemperatureCommand( - seqNum, mEndpoint, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -597,22 +554,16 @@ CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveHueCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -633,23 +584,17 @@ CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveSaturationCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorX, uint16_t colorY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -672,23 +617,17 @@ CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorCommand( - seqNum, mEndpoint, colorX, colorY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorTemperature, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -709,23 +648,17 @@ CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorTemperatureCommand( - seqNum, mEndpoint, colorTemperature, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t direction, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -748,23 +681,17 @@ CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveToHueCommand(seqNum, mEndpoint, hue, direction, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToHueAndSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -787,23 +714,17 @@ CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToHueAndSaturationCommand( - seqNum, mEndpoint, hue, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -824,23 +745,17 @@ CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToSaturationCommand( - seqNum, mEndpoint, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t stepX, int16_t stepY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepColorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -863,13 +778,10 @@ CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStepColorCommand(seqNum, mEndpoint, stepX, stepY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -877,10 +789,7 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu uint16_t transitionTime, uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepColorTemperatureCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -907,24 +816,17 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepColorTemperatureCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, - optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepHueCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -947,23 +849,17 @@ CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepHueCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepSaturationCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -986,22 +882,16 @@ CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepSaturationCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopMoveStepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1018,13 +908,10 @@ CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStopMoveStepCommand(seqNum, mEndpoint, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ColorControl Cluster Attributes @@ -1681,10 +1568,7 @@ CHIP_ERROR DescriptorCluster::ReadAttributeClusterRevision(Callback::Cancelable // DoorLock Cluster Commands CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearAllPinsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1696,20 +1580,15 @@ CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllPinsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearAllRfidsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1721,21 +1600,16 @@ CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllRfidsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1750,21 +1624,16 @@ CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1779,21 +1648,16 @@ CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1808,21 +1672,16 @@ CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1839,22 +1698,16 @@ CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1871,22 +1724,16 @@ CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1901,21 +1748,16 @@ CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t logIndex) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetLogRecordCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1930,21 +1772,16 @@ CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetLogRecordCommand(seqNum, mEndpoint, logIndex); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1959,21 +1796,16 @@ CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -1988,21 +1820,16 @@ CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetUserTypeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2017,21 +1844,16 @@ CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetUserTypeCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2048,22 +1870,16 @@ CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2080,22 +1896,16 @@ CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kLockDoorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2110,22 +1920,17 @@ CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterLockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint32_t localStartTime, uint32_t localEndTime, uint8_t operatingModeDuringHoliday) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetHolidayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2146,22 +1951,16 @@ CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetHolidayScheduleCommand( - seqNum, mEndpoint, scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetPinCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2182,22 +1981,16 @@ CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetPinCommand(seqNum, mEndpoint, userId, userStatus, userType, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan id) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetRfidCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2218,22 +2011,16 @@ CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetRfidCommand(seqNum, mEndpoint, userId, userStatus, userType, id); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userType) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetUserTypeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2250,22 +2037,17 @@ CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetUserTypeCommand(seqNum, mEndpoint, userId, userType); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint8_t daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetWeekdayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2292,22 +2074,16 @@ CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetWeekdayScheduleCommand( - seqNum, mEndpoint, scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint32_t localStartTime, uint32_t localEndTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetYeardayScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2328,22 +2104,16 @@ CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId, localStartTime, localEndTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnlockDoorCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2358,21 +2128,16 @@ CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterUnlockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t timeoutInSeconds, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUnlockWithTimeoutCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2389,13 +2154,10 @@ CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterUnlockWithTimeoutCommand(seqNum, mEndpoint, timeoutInSeconds, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // DoorLock Cluster Attributes @@ -2457,10 +2219,7 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc Callback::Cancelable * onFailureCallback, uint16_t expiryLengthSeconds, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kArmFailSafeCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2479,22 +2238,16 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGeneralCommissioningClusterArmFailSafeCommand(seqNum, mEndpoint, expiryLengthSeconds, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kCommissioningCompleteCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2506,22 +2259,17 @@ CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGeneralCommissioningClusterCommissioningCompleteCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t location, chip::ByteSpan countryCode, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetRegulatoryConfigCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2542,13 +2290,10 @@ CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGeneralCommissioningClusterSetRegulatoryConfigCommand( - seqNum, mEndpoint, location, countryCode, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // GeneralCommissioning Cluster Attributes @@ -2628,10 +2373,7 @@ CHIP_ERROR GroupKeyManagementCluster::ReadAttributeClusterRevision(Callback::Can CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2648,21 +2390,16 @@ CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterAddGroupCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddGroupIfIdentifyingCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2679,22 +2416,16 @@ CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterAddGroupIfIdentifyingCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t groupCount, uint16_t groupList) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetGroupMembershipCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2711,21 +2442,15 @@ CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterGetGroupMembershipCommand(seqNum, mEndpoint, groupCount, groupList); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllGroupsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2737,21 +2462,16 @@ CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveAllGroupsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2766,21 +2486,16 @@ CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kViewGroupCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2795,12 +2510,10 @@ CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterViewGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Groups Cluster Attributes @@ -2830,10 +2543,7 @@ CHIP_ERROR GroupsCluster::ReadAttributeClusterRevision(Callback::Cancelable * on CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t identifyTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2848,20 +2558,15 @@ CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyCommand(seqNum, mEndpoint, identifyTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kIdentifyQueryCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2873,12 +2578,10 @@ CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyQueryCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Identify Cluster Attributes @@ -2916,10 +2619,7 @@ CHIP_ERROR IdentifyCluster::ReadAttributeClusterRevision(Callback::Cancelable * CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2940,22 +2640,16 @@ CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveCommand(seqNum, mEndpoint, moveMode, rate, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToLevelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -2976,23 +2670,17 @@ CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelCommand(seqNum, mEndpoint, level, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveToLevelWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3009,22 +2697,16 @@ CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelWithOnOffCommand(seqNum, mEndpoint, level, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kMoveWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3041,22 +2723,17 @@ CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterMoveWithOnOffCommand(seqNum, mEndpoint, moveMode, rate); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3079,22 +2756,16 @@ CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStepWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3113,22 +2784,16 @@ CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepWithOnOffCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3145,20 +2810,15 @@ CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopCommand(seqNum, mEndpoint, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStopWithOnOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3170,12 +2830,10 @@ CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopWithOnOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LevelControl Cluster Attributes @@ -3220,10 +2878,7 @@ CHIP_ERROR LevelControlCluster::ReadAttributeClusterRevision(Callback::Cancelabl // LowPower Cluster Commands CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSleepCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3235,12 +2890,10 @@ CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLowPowerClusterSleepCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LowPower Cluster Attributes @@ -3263,10 +2916,7 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * Callback::Cancelable * onFailureCallback, chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddThreadNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3285,23 +2935,17 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddWiFiNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3322,23 +2966,17 @@ CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kDisableNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3357,23 +2995,17 @@ CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterDisableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kEnableNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3392,23 +3024,17 @@ CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterEnableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetLastNetworkCommissioningResultCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3423,23 +3049,17 @@ CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterGetLastNetworkCommissioningResultCommand(seqNum, mEndpoint, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3458,23 +3078,17 @@ CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterRemoveNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kScanNetworksCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3493,13 +3107,10 @@ CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterScanNetworksCommand(seqNum, mEndpoint, ssid, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable * onSuccessCallback, @@ -3507,10 +3118,7 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateThreadNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3529,23 +3137,17 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateWiFiNetworkCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3566,13 +3168,10 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // NetworkCommissioning Cluster Attributes @@ -3594,10 +3193,7 @@ CHIP_ERROR NetworkCommissioningCluster::ReadAttributeClusterRevision(Callback::C // OnOff Cluster Commands CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOffCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3609,20 +3205,15 @@ CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kOnCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3634,20 +3225,15 @@ CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback:: ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOnCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kToggleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3659,12 +3245,10 @@ CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterToggleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OnOff Cluster Attributes @@ -3707,10 +3291,7 @@ CHIP_ERROR OnOffCluster::ReadAttributeClusterRevision(Callback::Cancelable * onS CHIP_ERROR OperationalCredentialsCluster::RemoveAllFabrics(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllFabricsCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3722,22 +3303,17 @@ CHIP_ERROR OperationalCredentialsCluster::RemoveAllFabrics(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterRemoveAllFabricsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::RemoveFabric(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::FabricId fabricId, chip::NodeId nodeId, uint16_t vendorId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveFabricCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3756,22 +3332,16 @@ CHIP_ERROR OperationalCredentialsCluster::RemoveFabric(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeOperationalCredentialsClusterRemoveFabricCommand(seqNum, mEndpoint, fabricId, nodeId, vendorId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::SetFabric(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t vendorId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetFabricCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3786,21 +3356,16 @@ CHIP_ERROR OperationalCredentialsCluster::SetFabric(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOperationalCredentialsClusterSetFabricCommand(seqNum, mEndpoint, vendorId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan label) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kUpdateFabricLabelCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3815,13 +3380,10 @@ CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeOperationalCredentialsClusterUpdateFabricLabelCommand(seqNum, mEndpoint, label); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OperationalCredentials Cluster Attributes @@ -3955,10 +3517,7 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, chip::ByteSpan sceneName, chip::ClusterId clusterId, uint8_t length, uint8_t value) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kAddSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -3985,22 +3544,16 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterAddSceneCommand( - seqNum, mEndpoint, groupId, sceneId, transitionTime, sceneName, clusterId, length, value); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetSceneMembershipCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4015,21 +3568,16 @@ CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterGetSceneMembershipCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRecallSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4048,22 +3596,16 @@ CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeScenesClusterRecallSceneCommand(seqNum, mEndpoint, groupId, sceneId, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveAllScenesCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4078,21 +3620,16 @@ CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveAllScenesCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRemoveSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4109,21 +3646,16 @@ CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kStoreSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4140,21 +3672,16 @@ CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterStoreSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kViewSceneCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4171,12 +3698,10 @@ CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterViewSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Scenes Cluster Attributes @@ -4341,10 +3866,7 @@ CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeClusterRevision(Callback: // TestCluster Cluster Commands CHIP_ERROR TestClusterCluster::Test(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4356,20 +3878,15 @@ CHIP_ERROR TestClusterCluster::Test(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TestClusterCluster::TestNotHandled(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestNotHandledCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4381,20 +3898,15 @@ CHIP_ERROR TestClusterCluster::TestNotHandled(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestNotHandledCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR TestClusterCluster::TestSpecific(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kTestSpecificCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4406,12 +3918,10 @@ CHIP_ERROR TestClusterCluster::TestSpecific(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeTestClusterClusterTestSpecificCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // TestCluster Cluster Attributes @@ -4698,10 +4208,7 @@ CHIP_ERROR TestClusterCluster::ReadAttributeClusterRevision(Callback::Cancelable CHIP_ERROR ThermostatCluster::ClearWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kClearWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4713,20 +4220,15 @@ CHIP_ERROR ThermostatCluster::ClearWeeklySchedule(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterClearWeeklyScheduleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::GetRelayStatusLog(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetRelayStatusLogCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4738,21 +4240,16 @@ CHIP_ERROR ThermostatCluster::GetRelayStatusLog(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterGetRelayStatusLogCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::GetWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t daysToReturn, uint8_t modeToReturn) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kGetWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4769,23 +4266,17 @@ CHIP_ERROR ThermostatCluster::GetWeeklySchedule(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeThermostatClusterGetWeeklyScheduleCommand(seqNum, mEndpoint, daysToReturn, modeToReturn); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::SetWeeklySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t numberOfTransitionsForSequence, uint8_t dayOfWeekForSequence, uint8_t modeForSequence, uint8_t payload) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetWeeklyScheduleCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4806,22 +4297,16 @@ CHIP_ERROR ThermostatCluster::SetWeeklySchedule(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterSetWeeklyScheduleCommand( - seqNum, mEndpoint, numberOfTransitionsForSequence, dayOfWeekForSequence, modeForSequence, payload); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ThermostatCluster::SetpointRaiseLower(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t mode, int8_t amount) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); - (void) onSuccessCallback; - (void) onFailureCallback; app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kSetpointRaiseLowerCommandId, (chip::app::CommandPathFlags::kEndpointIdValid) }; @@ -4838,12 +4323,10 @@ CHIP_ERROR ThermostatCluster::SetpointRaiseLower(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->FinishCommand()); + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(onSuccessCallback, onFailureCallback); + return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeThermostatClusterSetpointRaiseLowerCommand(seqNum, mEndpoint, mode, amount); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Thermostat Cluster Attributes diff --git a/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp b/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp index 29e43f123a3708..e32e19d1dd2cb7 100644 --- a/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp +++ b/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp @@ -43,46 +43,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -92,64 +107,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -159,64 +166,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -226,64 +225,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -293,64 +284,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -360,64 +343,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -427,64 +402,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -494,128 +461,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 4: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -625,162 +536,82 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetHolidayScheduleResponseCallback(apCommandObj, scheduleId, status, localStartTime, - localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetHolidayScheduleResponseCallback( + apCommandObj, scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday); } break; } case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint16_t logEntryId; - bool logEntryIdExists = false; uint32_t timestamp; - bool timestampExists = false; uint8_t eventType; - bool eventTypeExists = false; uint8_t source; - bool sourceExists = false; uint8_t eventIdOrAlarmCode; - bool eventIdOrAlarmCodeExists = false; uint16_t userId; - bool userIdExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (logEntryIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(logEntryId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logEntryIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logEntryId); break; case 1: - if (timestampExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timestamp); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timestampExists = true; - validArgumentCount++; - } break; case 2: - if (eventTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventTypeExists = true; - validArgumentCount++; - } break; case 3: - if (sourceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(source); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sourceExists = true; - validArgumentCount++; - } break; case 4: - if (eventIdOrAlarmCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventIdOrAlarmCodeExists = true; - validArgumentCount++; - } break; case 5: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 6: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -790,114 +621,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetLogRecordResponseCallback(apCommandObj, logEntryId, timestamp, eventType, source, - eventIdOrAlarmCode, userId, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetLogRecordResponseCallback( + apCommandObj, logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast(pin)); } break; } case ZCL_GET_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -907,114 +694,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType, - const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType, + const_cast(pin)); } break; } case ZCL_GET_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * rfid; - bool rfidExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (rfidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(rfid); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rfidExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1024,81 +767,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType, - const_cast(rfid)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType, + const_cast(rfid)); } break; } case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (userIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1108,176 +831,84 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType); } break; } case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 8; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[8]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 4: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } break; case 5: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 6: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 7: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1287,129 +918,73 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, daysMask, - startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 8, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetWeekdayScheduleResponseCallback( + apCommandObj, scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute); } break; } case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (scheduleIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 4: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1419,65 +994,57 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, localStartTime, - localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status, + localStartTime, localEndTime); } break; } case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1487,64 +1054,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status); } break; } case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1554,64 +1113,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_SET_PIN_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1621,64 +1172,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status); } break; } case ZCL_SET_RFID_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1688,64 +1231,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status); } break; } case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1755,64 +1290,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status); } break; } case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1822,64 +1349,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1889,64 +1408,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status); } break; } case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -1956,64 +1467,56 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status); } break; } case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2023,36 +1526,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -2061,63 +1569,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2127,82 +1638,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2212,82 +1703,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } case ZCL_SET_REGULATORY_CONFIG_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2297,37 +1768,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -2336,62 +1812,65 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2401,97 +1880,65 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t capacity; - bool capacityExists = false; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (capacityExists) + 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; } - TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - capacityExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(capacity); break; case 1: - if (groupCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupCountExists = true; - validArgumentCount++; - } break; case 2: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2501,80 +1948,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList); } break; } case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2584,97 +2011,65 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2684,36 +2079,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = + emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast(groupName)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -2722,46 +2123,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t timeout; - bool timeoutExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (timeoutExists) + 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; } - TLVUnpackError = aDataTlv.Get(timeout); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2771,36 +2187,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -2809,63 +2230,66 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2875,82 +2299,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -2960,82 +2364,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3045,82 +2429,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3130,82 +2494,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3215,116 +2559,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; - bool wifiScanResultsExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; - bool threadScanResultsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; case 2: - if (wifiScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(wifiScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - wifiScanResultsExists = true; - validArgumentCount++; - } break; case 3: - if (threadScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(threadScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - threadScanResultsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3334,82 +2634,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterScanNetworksResponseCallback( + wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback( apCommandObj, errorCode, const_cast(debugText), wifiScanResults, threadScanResults); } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); - } break; } case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3419,82 +2699,62 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback( + apCommandObj, errorCode, const_cast(debugText)); } break; } case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (errorCodeExists) + 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; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3504,37 +2764,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode, - const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode, + const_cast(debugText)); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -3543,46 +2808,61 @@ 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_SET_FABRIC_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; chip::FabricId FabricId; - bool FabricIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (FabricIdExists) + 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; } - TLVUnpackError = aDataTlv.Get(FabricId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - FabricIdExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3592,37 +2872,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OperationalCredentials @@ -3631,78 +2916,69 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3712,129 +2988,73 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t status; - bool statusExists = false; uint8_t capacity; - bool capacityExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneCount; - bool sceneCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * sceneList; - bool sceneListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (capacityExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) - { - capacityExists = true; - validArgumentCount++; - } break; case 2: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 3: - if (sceneCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneCountExists = true; - validArgumentCount++; - } break; case 4: - if (sceneListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(sceneList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3844,81 +3064,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId, sceneCount, - sceneList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId, + sceneCount, sceneList); } break; } case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -3928,96 +3128,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId); } break; } case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4027,96 +3195,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4126,146 +3262,78 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId); } break; } case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (statusExists) + 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; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 3: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 4: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 5: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4275,37 +3343,42 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime, - const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime, + const_cast(sceneName), extensionFieldSets); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes @@ -4314,46 +3387,61 @@ 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: { - // 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. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t returnValue; - bool returnValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // 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())) { - case 0: - if (returnValueExists) + 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; } - TLVUnpackError = aDataTlv.Get(returnValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - returnValueExists = true; + 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 (TLVUnpackError != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != TLVUnpackError) { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); break; } } @@ -4363,36 +3451,41 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. 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. - emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + wasHandled = emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue); } break; } default: { // Unrecognized command ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + 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::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_TEST_CLUSTER_ID); - break; + 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::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace TestCluster @@ -4409,10 +3502,39 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + 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_NETWORK_COMMISSIONING_CLUSTER_ID: + clusters::NetworkCommissioning::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_TEST_CLUSTER_ID: + clusters::TestCluster::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; default: // Unrecognized cluster ID, error status will apply. - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, - Protocols::SecureChannel::kProtocolCodeGeneralFailure); + chip::app::CommandPathParams returnStatusParam = { aEndPointId, + 0, // GroupId + aClusterId, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + apCommandObj->AddStatusCode(&returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown cluster %" PRIx16, aClusterId); break; } From 03f63ea147b7e54e6b07bac3ecb0255ad2ccdefe Mon Sep 17 00:00:00 2001 From: Song Guo Date: Fri, 7 May 2021 01:29:56 +0800 Subject: [PATCH 14/17] [cluster] Implement IM specific response encoding in existing clusters --- .../door-lock-server-logging.cpp | 40 +- .../door-lock-server-schedule.cpp | 268 +++++++++-- .../door-lock-server-user.cpp | 407 ++++++++++++++--- .../clusters/groups-server/groups-server.cpp | 120 ++++- .../ias-zone-server/ias-zone-server.cpp | 2 +- src/app/clusters/identify/identify.cpp | 35 +- .../operational-credentials-server.cpp | 4 +- src/app/clusters/scenes/scenes.cpp | 428 ++++++++++++------ src/app/clusters/scenes/scenes.h | 9 +- .../zll-scenes-server/zll-scenes-server.c | 6 +- 10 files changed, 1030 insertions(+), 289 deletions(-) diff --git a/src/app/clusters/door-lock-server/door-lock-server-logging.cpp b/src/app/clusters/door-lock-server/door-lock-server-logging.cpp index a0ce8344c1fa6a..0c0c70458905a7 100644 --- a/src/app/clusters/door-lock-server/door-lock-server-logging.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server-logging.cpp @@ -122,6 +122,7 @@ bool emberAfDoorLockClusterGetLogRecordCallback(chip::app::Command * commandObj, { EmberStatus status; EmberAfPluginDoorLockServerLogEntry entry; + CHIP_ERROR err = CHIP_NO_ERROR; if (LOG_IS_EMPTY() || !emberAfPluginDoorLockServerGetLogEntry(&entryId, &entry)) { status = emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_INVALID_VALUE); @@ -132,15 +133,40 @@ bool emberAfDoorLockClusterGetLogRecordCallback(chip::app::Command * commandObj, } else { - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID, "vwuuuvs", entry.logEntryId, entry.timestamp, - entry.eventType, entry.source, entry.eventId, entry.userId, entry.pin); - - status = emberAfSendResponse(); - if (status != EMBER_SUCCESS) + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID, "vwuuuvs", entry.logEntryId, entry.timestamp, + entry.eventType, entry.source, entry.eventId, entry.userId, entry.pin); + + status = emberAfSendResponse(); + if (status != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send GetLogRecordResponse: 0x%X", status); + } + } + else { - emberAfDoorLockClusterPrintln("Failed to send GetLogRecordResponse: 0x%X", status); + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), entry.logEntryId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), entry.timestamp)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), entry.eventType)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(3), entry.source)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(4), entry.eventId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(5), entry.userId)); + SuccessOrExit(err = writer->PutBytes(TLV::ContextTag(6), entry.pin + 1, entry.pin[0])); + SuccessOrExit(err = commandObj->FinishCommand()); } } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } diff --git a/src/app/clusters/door-lock-server/door-lock-server-schedule.cpp b/src/app/clusters/door-lock-server/door-lock-server-schedule.cpp index f414e0ecc36455..1e089b8fe680dd 100644 --- a/src/app/clusters/door-lock-server/door-lock-server-schedule.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server-schedule.cpp @@ -45,6 +45,9 @@ #include "gen/command-id.h" #include +#include + +using namespace chip; static EmberAfPluginDoorLockServerWeekdayScheduleEntry weekdayScheduleTable[EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_WEEKDAY_SCHEDULE_TABLE_SIZE]; @@ -134,6 +137,7 @@ bool emberAfDoorLockClusterSetWeekdayScheduleCallback(chip::app::Command * comma uint8_t status = 0x00; uint8_t userPin = 0x00; uint16_t rfProgrammingEventMask = 0xffff; // event sent by default + CHIP_ERROR err = CHIP_NO_ERROR; if (!emAfPluginDoorLockServerCheckForSufficientSpace(scheduleId, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_WEEKDAY_SCHEDULE_TABLE_SIZE) || !emAfPluginDoorLockServerCheckForSufficientSpace(userId, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE)) @@ -153,9 +157,23 @@ bool emberAfDoorLockClusterSetWeekdayScheduleCallback(chip::app::Command * comma emberAfDoorLockClusterPrintln("***RX SET WEEKDAY SCHEDULE***"); printWeekdayScheduleTable(); } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); - emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); + emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } // get bitmask so we can check if we should send event notification emberAfReadServerAttribute(DOOR_LOCK_SERVER_ENDPOINT, ZCL_DOOR_LOCK_CLUSTER_ID, ZCL_RF_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID, @@ -168,7 +186,11 @@ bool emberAfDoorLockClusterSetWeekdayScheduleCallback(chip::app::Command * comma 0x00, 0x00, &userPin); SEND_COMMAND_UNICAST_TO_BINDINGS(); } - +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -178,19 +200,44 @@ bool emberAfDoorLockClusterGetWeekdayScheduleCallback(chip::app::Command * comma ((scheduleId > EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_WEEKDAY_SCHEDULE_TABLE_SIZE) ? EMBER_ZCL_STATUS_INVALID_FIELD : EMBER_ZCL_STATUS_SUCCESS); EmberAfDoorLockScheduleEntry * entry = &weekdayScheduleTable[0]; + CHIP_ERROR err = CHIP_NO_ERROR; if (zclStatus == EMBER_ZCL_STATUS_SUCCESS) { entry = &weekdayScheduleTable[scheduleId]; zclStatus = (!entry->inUse ? EMBER_ZCL_STATUS_NOT_FOUND : (entry->userId != userId ? EMBER_ZCL_STATUS_NOT_FOUND : EMBER_ZCL_STATUS_SUCCESS)); } + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, "uvuuuuuu", scheduleId, userId, zclStatus, + entry->daysMask, entry->startHour, entry->startMinute, entry->stopHour, entry->stopMinute); - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, "uvuuuuuu", scheduleId, userId, zclStatus, - entry->daysMask, entry->startHour, entry->startMinute, entry->stopHour, entry->stopMinute); - - sendResponse("GetWeekdayScheduleResponse"); - + sendResponse("GetWeekdayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), scheduleId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), userId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), zclStatus)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(3), entry->daysMask)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(4), entry->startHour)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(5), entry->startMinute)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(6), entry->stopHour)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(7), entry->stopMinute)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -199,17 +246,36 @@ bool emberAfDoorLockClusterClearWeekdayScheduleCallback(chip::app::Command * com EmberAfStatus zclStatus = ((scheduleId > EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_WEEKDAY_SCHEDULE_TABLE_SIZE) ? EMBER_ZCL_STATUS_INVALID_FIELD : EMBER_ZCL_STATUS_SUCCESS); + CHIP_ERROR err = CHIP_NO_ERROR; if (zclStatus == EMBER_ZCL_STATUS_SUCCESS) { weekdayScheduleTable[scheduleId].inUse = false; emAfPluginDoorLockServerSetPinUserType(userId, EMBER_ZCL_DOOR_LOCK_USER_TYPE_UNRESTRICTED); } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", zclStatus); - - sendResponse("ClearWeekdayScheduleResponse"); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", zclStatus); + sendResponse("ClearWeekdayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), zclStatus)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -217,6 +283,7 @@ bool emberAfDoorLockClusterSetYeardayScheduleCallback(chip::app::Command * comma uint32_t localStartTime, uint32_t localEndTime) { uint8_t status; + CHIP_ERROR err = CHIP_NO_ERROR; if (scheduleId >= EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_YEARDAY_SCHEDULE_TABLE_SIZE) { status = 0x01; // failure (per 7.3.2.17.15) @@ -229,11 +296,29 @@ bool emberAfDoorLockClusterSetYeardayScheduleCallback(chip::app::Command * comma yeardayScheduleTable[scheduleId].inUse = true; status = 0x00; // success (per 7.3.2.17.15) } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); - - sendResponse("SetYeardayScheduleResponse"); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); + sendResponse("SetYeardayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -241,6 +326,7 @@ bool emberAfDoorLockClusterGetYeardayScheduleCallback(chip::app::Command * comma { EmberAfPluginDoorLockServerYeardayScheduleEntry * entry = &yeardayScheduleTable[0]; EmberAfStatus zclStatus; + CHIP_ERROR err = CHIP_NO_ERROR; if (scheduleId >= EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_YEARDAY_SCHEDULE_TABLE_SIZE || userId >= EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE) { @@ -259,18 +345,41 @@ bool emberAfDoorLockClusterGetYeardayScheduleCallback(chip::app::Command * comma } } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, "uvuww", scheduleId, userId, zclStatus, - entry->localStartTime, entry->localEndTime); - - sendResponse("GetYeardayScheduleResponse"); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, "uvuww", scheduleId, userId, zclStatus, + entry->localStartTime, entry->localEndTime); + sendResponse("GetYeardayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), scheduleId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), userId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), zclStatus)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(3), entry->localStartTime)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(4), entry->localEndTime)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfDoorLockClusterClearYeardayScheduleCallback(chip::app::Command * commandObj, uint8_t scheduleId, uint16_t userId) { uint8_t status; + CHIP_ERROR err = CHIP_NO_ERROR; if (scheduleId >= EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_YEARDAY_SCHEDULE_TABLE_SIZE) { status = 0x01; // failure (per 7.3.2.17.17) @@ -281,11 +390,29 @@ bool emberAfDoorLockClusterClearYeardayScheduleCallback(chip::app::Command * com emAfPluginDoorLockServerSetPinUserType(userId, EMBER_ZCL_DOOR_LOCK_USER_TYPE_UNRESTRICTED); status = 0x00; // success (per 7.3.2.17.17) } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); - - sendResponse("ClearYeardayScheduleResponse"); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); + sendResponse("ClearYeardayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -294,6 +421,7 @@ bool emberAfDoorLockClusterSetHolidayScheduleCallback(chip::app::Command * comma uint8_t operatingModeDuringHoliday) { uint8_t status; + CHIP_ERROR err = CHIP_NO_ERROR; if (holidayScheduleId >= EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_HOLIDAY_SCHEDULE_TABLE_SIZE) { status = 0x01; // failure (per 7.3.2.17.18) @@ -308,11 +436,29 @@ bool emberAfDoorLockClusterSetHolidayScheduleCallback(chip::app::Command * comma holidayScheduleTable[holidayScheduleId].inUse = true; status = 0x00; // success (per 7.3.2.17.18) } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); - - sendResponse("SetHolidayScheduleResponse"); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); + sendResponse("SetHolidayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -320,6 +466,7 @@ bool emberAfDoorLockClusterGetHolidayScheduleCallback(chip::app::Command * comma { EmberAfPluginDoorLockServerHolidayScheduleEntry * entry = &holidayScheduleTable[0]; EmberAfStatus zclStatus; + CHIP_ERROR err = CHIP_NO_ERROR; if (holidayScheduleId >= EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_HOLIDAY_SCHEDULE_TABLE_SIZE) { zclStatus = EMBER_ZCL_STATUS_INVALID_FIELD; @@ -337,18 +484,41 @@ bool emberAfDoorLockClusterGetHolidayScheduleCallback(chip::app::Command * comma } } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, "uuwwu", holidayScheduleId, zclStatus, - entry->localStartTime, entry->localEndTime, entry->operatingModeDuringHoliday); - - sendResponse("GetHolidayScheduleResponse"); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, "uuwwu", holidayScheduleId, zclStatus, + entry->localStartTime, entry->localEndTime, entry->operatingModeDuringHoliday); + sendResponse("GetHolidayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), holidayScheduleId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), zclStatus)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), entry->localStartTime)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(3), entry->localEndTime)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(4), entry->operatingModeDuringHoliday)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfDoorLockClusterClearHolidayScheduleCallback(chip::app::Command * commandObj, uint8_t holidayScheduleId) { uint8_t status; + CHIP_ERROR err = CHIP_NO_ERROR; if (holidayScheduleId >= EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_YEARDAY_SCHEDULE_TABLE_SIZE) { status = 0x01; // failure (per 7.3.2.17.20) @@ -358,10 +528,28 @@ bool emberAfDoorLockClusterClearHolidayScheduleCallback(chip::app::Command * com holidayScheduleTable[holidayScheduleId].inUse = false; status = 0x00; // success (per 7.3.2.17.20) } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); - - sendResponse("ClearYeardayScheduleResponse"); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, "u", status); + sendResponse("ClearYeardayScheduleResponse"); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } diff --git a/src/app/clusters/door-lock-server/door-lock-server-user.cpp b/src/app/clusters/door-lock-server/door-lock-server-user.cpp index ad06e989ca0e05..6aaccb844135d0 100644 --- a/src/app/clusters/door-lock-server/door-lock-server-user.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server-user.cpp @@ -223,33 +223,74 @@ static uint8_t clearUserPinOrRfid(uint16_t userId, EmberAfPluginDoorLockServerUs bool emberAfDoorLockClusterGetUserTypeCallback(chip::app::Command * commandObj, uint16_t userId) { + CHIP_ERROR err = CHIP_NO_ERROR; if (emAfPluginDoorLockServerCheckForSufficientSpace(userId, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE)) { EmberAfPluginDoorLockServerUser * user = &pinUserTable[userId]; - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID, "vu", userId, user->type); - EmberStatus status = emberAfSendResponse(); - if (status != EMBER_SUCCESS) + if (commandObj == nullptr) { - emberAfDoorLockClusterPrintln("Failed to send GetUserTypeResponse: 0x%X", status); + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID, "vu", userId, user->type); + EmberStatus status = emberAfSendResponse(); + if (status != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send GetUserTypeResponse: 0x%X", status); + } } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), userId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), user->type)); + SuccessOrExit(err = commandObj->FinishCommand()); + } + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); } return true; } bool emberAfDoorLockClusterSetUserTypeCallback(chip::app::Command * commandObj, uint16_t userId, uint8_t userType) { + CHIP_ERROR err = CHIP_NO_ERROR; // TODO: Need to validate userType. https://github.com/project-chip/connectedhomeip/issues/3580 uint8_t status = (emAfPluginDoorLockServerSetPinUserType(userId, static_cast(userType)) ? 0x00 // success (per 7.3.2.17.21) : 0x01); // failure (per 7.3.2.17.21) - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID, "u", status); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID, "u", status); - EmberStatus emberStatus = emberAfSendResponse(); - if (emberStatus != EMBER_SUCCESS) + EmberStatus emberStatus = emberAfSendResponse(); + if (emberStatus != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send SetUserTypeResponse: 0x%X", emberStatus); + } + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) { - emberAfDoorLockClusterPrintln("Failed to send SetUserTypeResponse: 0x%X", emberStatus); + ChipLogError(Zcl, "Failed to encode response command."); } return true; } @@ -273,14 +314,28 @@ bool emAfPluginDoorLockServerSetPinUserType(uint16_t userId, EmberAfDoorLockUser bool emberAfDoorLockClusterSetPinCallback(chip::app::Command * commandObj, uint16_t userId, uint8_t userStatus, uint8_t userType, uint8_t * pin) { + CHIP_ERROR err = CHIP_NO_ERROR; // send response uint8_t status = setUser(userId, userStatus, userType, pin, pinUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE); - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_SET_PIN_RESPONSE_COMMAND_ID, "u", status); - emberAfSendResponse(); + uint16_t rfProgrammingEventMask = 0xffff; // send event by default + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_PIN_RESPONSE_COMMAND_ID, "u", status); + emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_PIN_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } // get bitmask so we can check if we should send event notification - uint16_t rfProgrammingEventMask = 0xffff; // send event by default emberAfReadServerAttribute(DOOR_LOCK_SERVER_ENDPOINT, ZCL_DOOR_LOCK_CLUSTER_ID, ZCL_RF_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID, (uint8_t *) &rfProgrammingEventMask, sizeof(rfProgrammingEventMask)); if ((rfProgrammingEventMask & EMBER_BIT(2)) && !status && (pin != NULL)) @@ -291,7 +346,11 @@ bool emberAfDoorLockClusterSetPinCallback(chip::app::Command * commandObj, uint1 0 /*emberAfGetCurrentTime() #2507*/, pin); SEND_COMMAND_UNICAST_TO_BINDINGS(); } - +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -313,14 +372,38 @@ static bool getSendPinOverTheAir(void) bool emberAfDoorLockClusterGetPinCallback(chip::app::Command * commandObj, uint16_t userId) { EmberAfPluginDoorLockServerUser user; - EmberStatus status; + EmberStatus status = EMBER_SUCCESS; + CHIP_ERROR err = CHIP_NO_ERROR; if (getUser(userId, pinUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE, &user)) { uint8_t fakePin = 0x00; - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_GET_PIN_RESPONSE_COMMAND_ID, "vuus", userId, user.status, user.type, - (getSendPinOverTheAir() ? user.code.pin : &fakePin)); - status = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_PIN_RESPONSE_COMMAND_ID, "vuus", userId, user.status, user.type, + (getSendPinOverTheAir() ? user.code.pin : &fakePin)); + status = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_PIN_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), userId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), user.status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), user.type)); + if (getSendPinOverTheAir()) + { + SuccessOrExit(err = writer->PutBytes(TLV::ContextTag(3), user.code.pin + 1, user.code.pin[0])); + } + else + { + SuccessOrExit(err = writer->PutBytes(TLV::ContextTag(3), nullptr, 0)); + } + SuccessOrExit(err = commandObj->FinishCommand()); + } } else { @@ -331,25 +414,44 @@ bool emberAfDoorLockClusterGetPinCallback(chip::app::Command * commandObj, uint1 { emberAfDoorLockClusterPrintln("Failed to send response to GetPin: 0x%X", status); } - +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfDoorLockClusterClearPinCallback(chip::app::Command * commandObj, uint16_t userId) { + CHIP_ERROR err = CHIP_NO_ERROR; uint8_t status = clearUserPinOrRfid(userId, pinUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE); - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID, "u", status); + // get bitmask so we can check if we should send event notification + uint16_t rfProgrammingEventMask = 0xffff; // event sent by default + uint8_t userPin = 0x00; // Zero length Zigbee string - EmberStatus emberStatus = emberAfSendResponse(); - if (emberStatus != EMBER_SUCCESS) + if (commandObj == nullptr) { - emberAfDoorLockClusterPrintln("Failed to send ClearPinResponse: 0x%X", emberStatus); + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID, "u", status); + + EmberStatus emberStatus = emberAfSendResponse(); + if (emberStatus != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send ClearPinResponse: 0x%X", emberStatus); + } + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); } - // get bitmask so we can check if we should send event notification - uint16_t rfProgrammingEventMask = 0xffff; // event sent by default - uint8_t userPin = 0x00; // Zero length Zigbee string emberAfReadServerAttribute(DOOR_LOCK_SERVER_ENDPOINT, ZCL_DOOR_LOCK_CLUSTER_ID, ZCL_RF_PROGRAMMING_EVENT_MASK_ATTRIBUTE_ID, (uint8_t *) &rfProgrammingEventMask, sizeof(rfProgrammingEventMask)); if ((rfProgrammingEventMask & EMBER_BIT(2)) && !status) @@ -366,25 +468,49 @@ bool emberAfDoorLockClusterClearPinCallback(chip::app::Command * commandObj, uin 0x00, 0x00, &userPin); SEND_COMMAND_UNICAST_TO_BINDINGS(); } - +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfDoorLockClusterClearAllPinsCallback(chip::app::Command * commandObj) { uint8_t i; + CHIP_ERROR err = CHIP_NO_ERROR; for (i = 0; i < EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE; i++) { clearUserPinOrRfid(i, pinUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_PIN_USER_TABLE_SIZE); } // 7.3.2.17.9 says that "0x00" indicates success. - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID, "u", 0x00); - EmberStatus status = emberAfSendResponse(); - if (status != EMBER_SUCCESS) + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID, "u", 0x00); + EmberStatus status = emberAfSendResponse(); + if (status != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send ClearAllPins: 0x%X", status); + } + } + else { - emberAfDoorLockClusterPrintln("Failed to send ClearAllPins: 0x%X", status); + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), 0)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); } return true; } @@ -395,15 +521,34 @@ bool emberAfDoorLockClusterClearAllPinsCallback(chip::app::Command * commandObj) bool emberAfDoorLockClusterSetRfidCallback(chip::app::Command * commandObj, uint16_t userId, uint8_t userStatus, uint8_t userType, uint8_t * rfid) { + CHIP_ERROR err = CHIP_NO_ERROR; uint8_t status = setUser(userId, userStatus, userType, rfid, rfidUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_RFID_USER_TABLE_SIZE); - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_SET_RFID_RESPONSE_COMMAND_ID, "u", status); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_RFID_RESPONSE_COMMAND_ID, "u", status); - EmberStatus emberStatus = emberAfSendResponse(); - if (emberStatus != EMBER_SUCCESS) + EmberStatus emberStatus = emberAfSendResponse(); + if (emberStatus != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send SetRfidResponse: 0x%X", emberStatus); + } + } + else { - emberAfDoorLockClusterPrintln("Failed to send SetRfidResponse: 0x%X", emberStatus); + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_SET_RFID_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); } return true; } @@ -411,12 +556,30 @@ bool emberAfDoorLockClusterSetRfidCallback(chip::app::Command * commandObj, uint bool emberAfDoorLockClusterGetRfidCallback(chip::app::Command * commandObj, uint16_t userId) { EmberAfPluginDoorLockServerUser user; - EmberStatus status; + EmberStatus status = EMBER_SUCCESS; + CHIP_ERROR err = CHIP_NO_ERROR; if (getUser(userId, rfidUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_RFID_USER_TABLE_SIZE, &user)) { - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_GET_RFID_RESPONSE_COMMAND_ID, "vuus", userId, user.status, user.type, user.code.pin); - status = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_RFID_RESPONSE_COMMAND_ID, "vuus", userId, user.status, user.type, user.code.pin); + status = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_GET_RFID_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), userId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), user.status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), user.type)); + SuccessOrExit(err = writer->PutBytes(TLV::ContextTag(3), user.code.pin + 1, user.code.pin[0])); + SuccessOrExit(err = commandObj->FinishCommand()); + } } else { @@ -427,38 +590,83 @@ bool emberAfDoorLockClusterGetRfidCallback(chip::app::Command * commandObj, uint { emberAfDoorLockClusterPrintln("Failed to send response to GetRfid: 0x%X", status); } - +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfDoorLockClusterClearRfidCallback(chip::app::Command * commandObj, uint16_t userId) { + CHIP_ERROR err = CHIP_NO_ERROR; uint8_t status = clearUserPinOrRfid(userId, rfidUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_RFID_USER_TABLE_SIZE); - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID, "u", status); - EmberStatus emberStatus = emberAfSendResponse(); - if (emberStatus != EMBER_SUCCESS) + if (commandObj == nullptr) { - emberAfDoorLockClusterPrintln("Failed to send ClearRfidResponse: 0x%X", emberStatus); + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID, "u", status); + + EmberStatus emberStatus = emberAfSendResponse(); + + if (emberStatus != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send ClearRfidResponse: 0x%X", emberStatus); + } + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); } return true; } bool emberAfDoorLockClusterClearAllRfidsCallback(chip::app::Command * commandObj) { + CHIP_ERROR err = CHIP_NO_ERROR; for (uint8_t i = 0; i < EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_RFID_USER_TABLE_SIZE; i++) { clearUserPinOrRfid(i, rfidUserTable, EMBER_AF_PLUGIN_DOOR_LOCK_SERVER_RFID_USER_TABLE_SIZE); } // 7.3.2.17.26 says that "0x00" indicates success. - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID, "u", 0x00); - EmberStatus status = emberAfSendResponse(); - if (status != EMBER_SUCCESS) + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID, "u", 0x00); + EmberStatus status = emberAfSendResponse(); + if (status != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send ClearAllRfidsResponse: 0x%X", status); + } + } + else { - emberAfDoorLockClusterPrintln("Failed to send ClearAllRfidsResponse: 0x%X", status); + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), 0)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); } return true; } @@ -525,6 +733,7 @@ bool emberAfDoorLockClusterLockDoorCallback(chip::app::Command * commandObj, uin bool doorLocked = false; uint8_t lockStateLocked = 0x01; uint16_t rfOperationEventMask = 0xffff; // will send events by default + CHIP_ERROR err = CHIP_NO_ERROR; emberAfDoorLockClusterPrint("LOCK DOOR "); printSuccessOrFailure(pinVerified); @@ -541,10 +750,23 @@ bool emberAfDoorLockClusterLockDoorCallback(chip::app::Command * commandObj, uin } // send response - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID, "u", - doorLocked ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE); - emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID, "u", + doorLocked ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE); + emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), doorLocked ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE)); + SuccessOrExit(err = commandObj->FinishCommand()); + } // check if we should send event notification emberAfReadServerAttribute(DOOR_LOCK_SERVER_ENDPOINT, ZCL_DOOR_LOCK_CLUSTER_ID, ZCL_RF_OPERATION_EVENT_MASK_ATTRIBUTE_ID, @@ -568,7 +790,11 @@ bool emberAfDoorLockClusterLockDoorCallback(chip::app::Command * commandObj, uin } } SEND_COMMAND_UNICAST_TO_BINDINGS(); - +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -579,6 +805,8 @@ bool emberAfDoorLockClusterUnlockDoorCallback(chip::app::Command * commandObj, u bool doorUnlocked = false; uint8_t lockStateUnlocked = 0x02; uint16_t rfOperationEventMask = 0xffff; // sends event by default + CHIP_ERROR err = CHIP_NO_ERROR; + emberAfDoorLockClusterPrint("UNLOCK DOOR "); printSuccessOrFailure(pinVerified); @@ -592,10 +820,23 @@ bool emberAfDoorLockClusterUnlockDoorCallback(chip::app::Command * commandObj, u &lockStateUnlocked, ZCL_INT8U_ATTRIBUTE_TYPE); } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID, "u", - doorUnlocked ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE); - emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID, "u", + doorUnlocked ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE); + emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), doorUnlocked ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE)); + SuccessOrExit(err = commandObj->FinishCommand()); + } // get bitmask so we can check if we should send event notification emberAfReadServerAttribute(DOOR_LOCK_SERVER_ENDPOINT, ZCL_DOOR_LOCK_CLUSTER_ID, ZCL_RF_OPERATION_EVENT_MASK_ATTRIBUTE_ID, @@ -610,7 +851,11 @@ bool emberAfDoorLockClusterUnlockDoorCallback(chip::app::Command * commandObj, u 0 /*emberAfGetCurrentTime() #2507 */, pin); SEND_COMMAND_UNICAST_TO_BINDINGS(); } - +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -754,6 +999,8 @@ bool emberAfDoorLockClusterUnlockWithTimeoutCallback(chip::app::Command * comman { uint8_t userId; uint8_t status; + CHIP_ERROR err = CHIP_NO_ERROR; + if (verifyPin(pin, &userId)) { uint8_t lockState = EMBER_ZCL_DOOR_LOCK_STATE_LOCKED; @@ -772,14 +1019,32 @@ bool emberAfDoorLockClusterUnlockWithTimeoutCallback(chip::app::Command * comman status = 0x01; // failure (per 7.3.2.17.4) } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, - ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID, "u", status); - EmberStatus emberStatus = emberAfSendResponse(); - if (emberStatus != EMBER_SUCCESS) + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID, "u", status); + EmberStatus emberStatus = emberAfSendResponse(); + if (emberStatus != EMBER_SUCCESS) + { + emberAfDoorLockClusterPrintln("Failed to send UnlockWithTimeoutResponse: 0x%X", status); + } + } + else { - emberAfDoorLockClusterPrintln("Failed to send UnlockWithTimeoutResponse: 0x%X", status); + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_DOOR_LOCK_CLUSTER_ID, + ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); } - return true; } diff --git a/src/app/clusters/groups-server/groups-server.cpp b/src/app/clusters/groups-server/groups-server.cpp index f1332808270d60..d1c72926bf2366 100644 --- a/src/app/clusters/groups-server/groups-server.cpp +++ b/src/app/clusters/groups-server/groups-server.cpp @@ -155,6 +155,7 @@ static EmberAfStatus removeEntryFromGroupTable(EndpointId endpoint, GroupId grou bool emberAfGroupsClusterAddGroupCallback(chip::app::Command * commandObj, GroupId groupId, uint8_t * groupName) { EmberAfStatus status; + CHIP_ERROR err = CHIP_NO_ERROR; emberAfGroupsClusterPrint("RX: AddGroup 0x%2x, \"", groupId); emberAfGroupsClusterPrintString(groupName); @@ -168,16 +169,36 @@ bool emberAfGroupsClusterAddGroupCallback(chip::app::Command * commandObj, Group { return true; } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, - ZCL_ADD_GROUP_RESPONSE_COMMAND_ID, "uv", status, groupId); - emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, + ZCL_ADD_GROUP_RESPONSE_COMMAND_ID, "uv", status, groupId); + emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_GROUPS_CLUSTER_ID, + ZCL_ADD_GROUP_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = commandObj->FinishCommand()); + } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfGroupsClusterViewGroupCallback(chip::app::Command * commandObj, GroupId groupId) { - EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND; - EmberStatus sendStatus; + EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND; + EmberStatus sendStatus = EMBER_SUCCESS; + CHIP_ERROR err = CHIP_NO_ERROR; uint8_t groupName[ZCL_GROUPS_CLUSTER_MAXIMUM_NAME_LENGTH + 1] = { 0 }; // Get the group name, if supported @@ -196,14 +217,33 @@ bool emberAfGroupsClusterViewGroupCallback(chip::app::Command * commandObj, Grou { status = EMBER_ZCL_STATUS_SUCCESS; } - - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, - ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID, "uvs", status, groupId, groupName); - sendStatus = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, + ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID, "uvs", status, groupId, groupName); + sendStatus = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_GROUPS_CLUSTER_ID, + ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(2), reinterpret_cast(&groupName[1]), groupName[0])); + SuccessOrExit(err = commandObj->FinishCommand()); + } if (EMBER_SUCCESS != sendStatus) { emberAfGroupsClusterPrintln("Groups: failed to send %s response: 0x%x", "view_group", sendStatus); } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -214,6 +254,7 @@ bool emberAfGroupsClusterGetGroupMembershipCallback(chip::app::Command * command uint8_t count = 0; uint8_t list[EMBER_BINDING_TABLE_SIZE << 1]; uint8_t listLen = 0; + CHIP_ERROR err = CHIP_NO_ERROR; emberAfGroupsClusterPrint("RX: GetGroupMembership 0x%x,", groupCount); for (i = 0; i < groupCount; i++) @@ -273,9 +314,25 @@ bool emberAfGroupsClusterGetGroupMembershipCallback(chip::app::Command * command // added. Each group requires a binding and, because the binding table is // used for other purposes besides groups, we can't be sure what the // capacity will be in the future. - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, - ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID, "uub", 0xFF, count, list, listLen); - status = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, + ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID, "uub", 0xFF, count, list, listLen); + status = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_GROUPS_CLUSTER_ID, + ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), 0xff)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), count)); + SuccessOrExit(err = writer->PutBytes(TLV::ContextTag(2), list, listLen)); + SuccessOrExit(err = commandObj->FinishCommand()); + } } else { @@ -286,13 +343,19 @@ bool emberAfGroupsClusterGetGroupMembershipCallback(chip::app::Command * command emberAfGroupsClusterPrintln("Groups: failed to send %s: 0x%x", (groupCount == 0 || count != 0) ? "get_group_membership response" : "default_response", status); } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfGroupsClusterRemoveGroupCallback(chip::app::Command * commandObj, GroupId groupId) { EmberAfStatus status; - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; + CHIP_ERROR err = CHIP_NO_ERROR; emberAfGroupsClusterPrintln("RX: RemoveGroup 0x%2x", groupId); @@ -309,20 +372,39 @@ bool emberAfGroupsClusterRemoveGroupCallback(chip::app::Command * commandObj, Gr // associated with it. ZCL6: 3.6.2.3.5: "Note that if a group is // removed the scenes associated with that group SHOULD be removed." emberAfScenesClusterRemoveScenesInGroupCallback(emberAfCurrentEndpoint(), groupId); - - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, - ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID, "uv", status, groupId); - sendStatus = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_GROUPS_CLUSTER_ID, + ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID, "uv", status, groupId); + sendStatus = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_GROUPS_CLUSTER_ID, + ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = commandObj->FinishCommand()); + } if (EMBER_SUCCESS != sendStatus) { emberAfGroupsClusterPrintln("Groups: failed to send %s response: 0x%x", "remove_group", sendStatus); } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfGroupsClusterRemoveAllGroupsCallback(chip::app::Command * commandObj) { - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; uint8_t i; EndpointId endpoint = emberAfCurrentEndpoint(); bool success = true; @@ -371,7 +453,7 @@ bool emberAfGroupsClusterRemoveAllGroupsCallback(chip::app::Command * commandObj bool emberAfGroupsClusterAddGroupIfIdentifyingCallback(chip::app::Command * commandObj, GroupId groupId, uint8_t * groupName) { EmberAfStatus status; - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; emberAfGroupsClusterPrint("RX: AddGroupIfIdentifying 0x%2x, \"", groupId); emberAfGroupsClusterPrintString(groupName); diff --git a/src/app/clusters/ias-zone-server/ias-zone-server.cpp b/src/app/clusters/ias-zone-server/ias-zone-server.cpp index 8cdf8b7209161f..50723c4cc8c721 100644 --- a/src/app/clusters/ias-zone-server/ias-zone-server.cpp +++ b/src/app/clusters/ias-zone-server/ias-zone-server.cpp @@ -410,7 +410,7 @@ EmberStatus emberAfPluginIasZoneServerUpdateZoneStatus(EndpointId endpoint, uint newBufferEntry.status = newStatus; newBufferEntry.eventTimeMs = System::Layer::GetClock_MonotonicMS(); #endif - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; emberAfWriteServerAttribute(endpoint, ZCL_IAS_ZONE_CLUSTER_ID, ZCL_ZONE_STATUS_ATTRIBUTE_ID, (uint8_t *) &newStatus, ZCL_INT16U_ATTRIBUTE_TYPE); diff --git a/src/app/clusters/identify/identify.cpp b/src/app/clusters/identify/identify.cpp index 9d0d1d5a855383..7ba92c0ba5654e 100644 --- a/src/app/clusters/identify/identify.cpp +++ b/src/app/clusters/identify/identify.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include "gen/attribute-id.h" #include "gen/attribute-type.h" @@ -105,7 +106,7 @@ void emberAfIdentifyClusterServerAttributeChangedCallback(EndpointId endpoint, A bool emberAfIdentifyClusterIdentifyCallback(chip::app::Command * commandObj, uint16_t time) { - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; // This Identify callback writes the new attribute, which will trigger the // Attribute Changed callback above, which in turn will schedule or cancel the // tick. Because of this, the tick does not have to be scheduled here. @@ -123,8 +124,9 @@ bool emberAfIdentifyClusterIdentifyCallback(chip::app::Command * commandObj, uin bool emberAfIdentifyClusterIdentifyQueryCallback(chip::app::Command * commandObj) { EmberAfStatus status; - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; uint16_t identifyTime; + CHIP_ERROR err = CHIP_NO_ERROR; emberAfIdentifyClusterPrintln("RX identify:QUERY"); @@ -154,9 +156,32 @@ bool emberAfIdentifyClusterIdentifyQueryCallback(chip::app::Command * commandObj } emberAfIdentifyClusterPrintln("Identifying for %d more seconds", identifyTime); - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_IDENTIFY_CLUSTER_ID, - ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID, "v", identifyTime); - sendStatus = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_IDENTIFY_CLUSTER_ID, + ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID, "v", identifyTime); + sendStatus = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_IDENTIFY_CLUSTER_ID, + ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + + VerifyOrExit(commandObj != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), identifyTime)); + SuccessOrExit(err = commandObj->FinishCommand()); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } if (EMBER_SUCCESS != sendStatus) { emberAfIdentifyClusterPrintln("Identify: failed to send %s response: 0x%x", "query", sendStatus); diff --git a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp index 912df1ba916543..f48497f3fa5693 100644 --- a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp +++ b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp @@ -208,7 +208,7 @@ bool emberAfOperationalCredentialsClusterRemoveFabricCallback(chip::app::Command EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; AdminPairingInfo * admin; AdminId adminId; - CHIP_ERROR err; + CHIP_ERROR err = CHIP_NO_ERROR; // Fetch matching admin admin = GetGlobalAdminPairingTable().FindAdminForNode(fabricId, nodeId, vendorId); @@ -232,7 +232,7 @@ bool emberAfOperationalCredentialsClusterSetFabricCallback(chip::app::Command * EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; EmberStatus sendStatus = EMBER_SUCCESS; - CHIP_ERROR err; + CHIP_ERROR err = CHIP_NO_ERROR; // Fetch current admin AdminPairingInfo * admin = retrieveCurrentAdmin(); diff --git a/src/app/clusters/scenes/scenes.cpp b/src/app/clusters/scenes/scenes.cpp index fc8e881dc8b8c5..99702c70aa00ac 100644 --- a/src/app/clusters/scenes/scenes.cpp +++ b/src/app/clusters/scenes/scenes.cpp @@ -217,19 +217,20 @@ void emAfPluginScenesServerPrintInfo(void) bool emberAfScenesClusterAddSceneCallback(chip::app::Command * commandObj, GroupId groupId, uint8_t sceneId, uint16_t transitionTime, uint8_t * sceneName, uint8_t * extensionFieldSets) { - return emberAfPluginScenesServerParseAddScene(emberAfCurrentCommand(), groupId, sceneId, transitionTime, sceneName, + return emberAfPluginScenesServerParseAddScene(commandObj, emberAfCurrentCommand(), groupId, sceneId, transitionTime, sceneName, extensionFieldSets); } bool emberAfScenesClusterViewSceneCallback(chip::app::Command * commandObj, GroupId groupId, uint8_t sceneId) { - return emberAfPluginScenesServerParseViewScene(emberAfCurrentCommand(), groupId, sceneId); + return emberAfPluginScenesServerParseViewScene(commandObj, emberAfCurrentCommand(), groupId, sceneId); } bool emberAfScenesClusterRemoveSceneCallback(chip::app::Command * commandObj, GroupId groupId, uint8_t sceneId) { - EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND; - EmberStatus sendStatus; + EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND; + EmberStatus sendStatus = EMBER_SUCCESS; + CHIP_ERROR err = CHIP_NO_ERROR; emberAfScenesClusterPrintln("RX: RemoveScene 0x%2x, 0x%x", groupId, sceneId); @@ -260,21 +261,43 @@ bool emberAfScenesClusterRemoveSceneCallback(chip::app::Command * commandObj, Gr // single device. if (emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST || emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST_REPLY) { - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, - ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID, "uvu", status, groupId, sceneId); - sendStatus = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, + ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID, "uvu", status, groupId, sceneId); + sendStatus = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_SCENES_CLUSTER_ID, + ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), sceneId)); + SuccessOrExit(err = commandObj->FinishCommand()); + } if (EMBER_SUCCESS != sendStatus) { emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "remove_scene", sendStatus); } } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfScenesClusterRemoveAllScenesCallback(chip::app::Command * commandObj, GroupId groupId) { - EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_FIELD; - EmberStatus sendStatus; + EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_FIELD; + EmberStatus sendStatus = EMBER_SUCCESS; + CHIP_ERROR err = CHIP_NO_ERROR; emberAfScenesClusterPrintln("RX: RemoveAllScenes 0x%2x", groupId); @@ -300,22 +323,44 @@ bool emberAfScenesClusterRemoveAllScenesCallback(chip::app::Command * commandObj // to a single device. if (emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST || emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST_REPLY) { - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, - ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID, "uv", status, groupId); - sendStatus = emberAfSendResponse(); + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, + ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID, "uv", status, groupId); + + sendStatus = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_SCENES_CLUSTER_ID, + ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = commandObj->FinishCommand()); + } if (EMBER_SUCCESS != sendStatus) { emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "remove_all_scenes", sendStatus); } } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } bool emberAfScenesClusterStoreSceneCallback(chip::app::Command * commandObj, GroupId groupId, uint8_t sceneId) { EmberAfStatus status; - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; + CHIP_ERROR err = CHIP_NO_ERROR; emberAfScenesClusterPrintln("RX: StoreScene 0x%2x, 0x%x", groupId, sceneId); status = emberAfScenesClusterStoreCurrentSceneCallback(emberAfCurrentEndpoint(), groupId, sceneId); @@ -323,14 +368,36 @@ bool emberAfScenesClusterStoreSceneCallback(chip::app::Command * commandObj, Gro // single device. if (emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST || emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST_REPLY) { - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, - ZCL_STORE_SCENE_RESPONSE_COMMAND_ID, "uvu", status, groupId, sceneId); - sendStatus = emberAfSendResponse(); + + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, + ZCL_STORE_SCENE_RESPONSE_COMMAND_ID, "uvu", status, groupId, sceneId); + sendStatus = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_SCENES_CLUSTER_ID, + ZCL_STORE_SCENE_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), sceneId)); + SuccessOrExit(err = commandObj->FinishCommand()); + } if (EMBER_SUCCESS != sendStatus) { emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "store_scene", sendStatus); } } +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -351,7 +418,7 @@ bool emberAfScenesClusterRecallSceneCallback(chip::app::Command * commandObj, Gr // value of TransitionTime. EmberAfStatus status; - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; emberAfScenesClusterPrintln("RX: RecallScene 0x%2x, 0x%x", groupId, sceneId); status = emberAfScenesClusterRecallSavedSceneCallback(emberAfCurrentEndpoint(), groupId, sceneId); #ifdef EMBER_AF_PLUGIN_ZLL_SCENES_SERVER @@ -370,9 +437,11 @@ bool emberAfScenesClusterRecallSceneCallback(chip::app::Command * commandObj, Gr bool emberAfScenesClusterGetSceneMembershipCallback(chip::app::Command * commandObj, GroupId groupId) { - EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; - EmberStatus sendStatus; - uint8_t sceneCount = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + EmberStatus sendStatus = EMBER_SUCCESS; + uint8_t sceneCount = 0; + uint8_t sceneList[EMBER_AF_PLUGIN_SCENES_TABLE_SIZE]; emberAfScenesClusterPrintln("RX: GetSceneMembership 0x%2x", groupId); @@ -381,16 +450,9 @@ bool emberAfScenesClusterGetSceneMembershipCallback(chip::app::Command * command status = EMBER_ZCL_STATUS_INVALID_FIELD; } - // The status, capacity, and group id are always included in the response, but - // the scene count and scene list are only included if the group id matched. - emberAfFillExternalBuffer( - (ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT | EMBER_AF_DEFAULT_RESPONSE_POLICY_RESPONSES), - ZCL_SCENES_CLUSTER_ID, ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID, "uuv", status, - (EMBER_AF_PLUGIN_SCENES_TABLE_SIZE - emberAfPluginScenesServerNumSceneEntriesInUse()), // capacity - groupId); if (status == EMBER_ZCL_STATUS_SUCCESS) { - uint8_t i, sceneList[EMBER_AF_PLUGIN_SCENES_TABLE_SIZE]; + uint8_t i; for (i = 0; i < EMBER_AF_PLUGIN_SCENES_TABLE_SIZE; i++) { EmberAfSceneTableEntry entry; @@ -408,17 +470,50 @@ bool emberAfScenesClusterGetSceneMembershipCallback(chip::app::Command * command } } - // Get Scene Membership commands are only responded to when they are - // addressed to a single device or when an entry in the table matches. - if (emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST || emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST_REPLY || - sceneCount != 0) + if (commandObj == nullptr) { - sendStatus = emberAfSendResponse(); - if (EMBER_SUCCESS != sendStatus) + // The status, capacity, and group id are always included in the response, but + // the scene count and scene list are only included if the group id matched. + emberAfFillExternalBuffer( + (ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT | EMBER_AF_DEFAULT_RESPONSE_POLICY_RESPONSES), + ZCL_SCENES_CLUSTER_ID, ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID, "uuv", status, + (EMBER_AF_PLUGIN_SCENES_TABLE_SIZE - emberAfPluginScenesServerNumSceneEntriesInUse()), // capacity + groupId); + + // Get Scene Membership commands are only responded to when they are + // addressed to a single device or when an entry in the table matches. + if (emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST || + emberAfCurrentCommand()->type == EMBER_INCOMING_UNICAST_REPLY || sceneCount != 0) { - emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "get_scene_membership", sendStatus); + sendStatus = emberAfSendResponse(); + if (EMBER_SUCCESS != sendStatus) + { + emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "get_scene_membership", sendStatus); + } } } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_SCENES_CLUSTER_ID, + ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), + (EMBER_AF_PLUGIN_SCENES_TABLE_SIZE - emberAfPluginScenesServerNumSceneEntriesInUse()))); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), groupId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(3), sceneCount)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(4), chip::ByteSpan(sceneList, sceneCount))); + SuccessOrExit(err = commandObj->FinishCommand()); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } @@ -661,12 +756,14 @@ EmberAfStatus emberAfScenesClusterRecallSavedSceneCallback(EndpointId endpoint, return EMBER_ZCL_STATUS_NOT_FOUND; } -bool emberAfPluginScenesServerParseAddScene(const EmberAfClusterCommand * cmd, GroupId groupId, uint8_t sceneId, - uint16_t transitionTime, uint8_t * sceneName, uint8_t * extensionFieldSets) +bool emberAfPluginScenesServerParseAddScene(chip::app::Command * commandObj, const EmberAfClusterCommand * cmd, GroupId groupId, + uint8_t sceneId, uint16_t transitionTime, uint8_t * sceneName, + uint8_t * extensionFieldSets) { + CHIP_ERROR err = CHIP_NO_ERROR; EmberAfSceneTableEntry entry; EmberAfStatus status; - EmberStatus sendStatus; + EmberStatus sendStatus = EMBER_SUCCESS; bool enhanced = (cmd->commandId == ZCL_ENHANCED_ADD_SCENE_COMMAND_ID); uint16_t extensionFieldSetsLen = static_cast( cmd->bufLen - @@ -975,24 +1072,51 @@ bool emberAfPluginScenesServerParseAddScene(const EmberAfClusterCommand * cmd, G { return true; } - emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, - (enhanced ? ZCL_ENHANCED_ADD_SCENE_RESPONSE_COMMAND_ID : ZCL_ADD_SCENE_RESPONSE_COMMAND_ID), "uvu", - status, groupId, sceneId); - sendStatus = emberAfSendResponse(); + + if (commandObj == nullptr) + { + emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT), ZCL_SCENES_CLUSTER_ID, + (enhanced ? ZCL_ENHANCED_ADD_SCENE_RESPONSE_COMMAND_ID : ZCL_ADD_SCENE_RESPONSE_COMMAND_ID), + "uvu", status, groupId, sceneId); + sendStatus = emberAfSendResponse(); + } + else + { + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_SCENES_CLUSTER_ID, + ZCL_ADD_SCENE_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + if (enhanced) + { + cmdParams.mCommandId = ZCL_ENHANCED_ADD_SCENE_RESPONSE_COMMAND_ID; + } + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), sceneId)); + SuccessOrExit(err = commandObj->FinishCommand()); + } if (EMBER_SUCCESS != sendStatus) { emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "add_scene", sendStatus); } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } -bool emberAfPluginScenesServerParseViewScene(const EmberAfClusterCommand * cmd, GroupId groupId, uint8_t sceneId) +bool emberAfPluginScenesServerParseViewScene(chip::app::Command * commandObj, const EmberAfClusterCommand * cmd, GroupId groupId, + uint8_t sceneId) { + CHIP_ERROR err = CHIP_NO_ERROR; EmberAfSceneTableEntry entry = {}; EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND; - EmberStatus sendStatus; - bool enhanced = (cmd->commandId == ZCL_ENHANCED_VIEW_SCENE_COMMAND_ID); - EndpointId endpoint = cmd->apsFrame->destinationEndpoint; + bool enhanced = (cmd->commandId == ZCL_ENHANCED_VIEW_SCENE_COMMAND_ID); + EndpointId endpoint = cmd->apsFrame->destinationEndpoint; emberAfScenesClusterPrintln("RX: %pViewScene 0x%2x, 0x%x", (enhanced ? "Enhanced" : ""), groupId, sceneId); @@ -1018,97 +1142,119 @@ bool emberAfPluginScenesServerParseViewScene(const EmberAfClusterCommand * cmd, // The status, group id, and scene id are always included in the response, but // the transition time, name, and extension fields are only included if the // scene was found. - emberAfFillExternalBuffer( - (ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT | EMBER_AF_DEFAULT_RESPONSE_POLICY_RESPONSES), - ZCL_SCENES_CLUSTER_ID, (enhanced ? ZCL_ENHANCED_VIEW_SCENE_RESPONSE_COMMAND_ID : ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID), "uvu", - status, groupId, sceneId); - if (status == EMBER_ZCL_STATUS_SUCCESS) + app::CommandPathParams cmdParams = { emberAfCurrentEndpoint(), /* group id */ 0, ZCL_SCENES_CLUSTER_ID, + ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID, (chip::app::CommandPathFlags::kEndpointIdValid) }; + if (enhanced) { - // The transition time is returned in seconds in the regular version of the - // command and tenths of a second in the enhanced version. - emberAfPutInt16uInResp( - static_cast(enhanced ? entry.transitionTime * 10 + entry.transitionTime100ms : entry.transitionTime)); + cmdParams.mCommandId = ZCL_ENHANCED_VIEW_SCENE_RESPONSE_COMMAND_ID; + } + TLV::TLVWriter * writer = nullptr; + SuccessOrExit(err = commandObj->PrepareCommand(&cmdParams)); + VerifyOrExit((writer = commandObj->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + SuccessOrExit(err = writer->Put(TLV::ContextTag(0), status)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(1), groupId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(2), sceneId)); + SuccessOrExit(err = writer->Put(TLV::ContextTag(3), + static_cast(enhanced ? entry.transitionTime * 10 + entry.transitionTime100ms + : entry.transitionTime))); #ifdef EMBER_AF_PLUGIN_SCENES_NAME_SUPPORT - emberAfPutStringInResp(entry.name); + SuccessOrExit(err = writer->Put(TLV::ContextTag(4), entry.name)); #else - emberAfPutInt8uInResp(0); // name length + SuccessOrExit(err = writer->PutString(TLV::ContextTag(4), "")); #endif -#ifdef ZCL_USING_ON_OFF_CLUSTER_SERVER - if (entry.hasOnOffValue) - { - emberAfPutInt16uInResp(ZCL_ON_OFF_CLUSTER_ID); - emberAfPutInt8uInResp(1); // length - emberAfPutInt8uInResp(entry.onOffValue); - } -#endif -#ifdef ZCL_USING_LEVEL_CONTROL_CLUSTER_SERVER - if (entry.hasCurrentLevelValue) - { - emberAfPutInt16uInResp(ZCL_LEVEL_CONTROL_CLUSTER_ID); - emberAfPutInt8uInResp(1); // length - emberAfPutInt8uInResp(entry.currentLevelValue); - } -#endif -#ifdef ZCL_USING_THERMOSTAT_CLUSTER_SERVER - if (entry.hasOccupiedCoolingSetpointValue) + // #6620: Need the build the array for response. + SuccessOrExit(err = writer->Put(TLV::ContextTag(5), chip::ByteSpan(nullptr, 0))); + SuccessOrExit(err = commandObj->FinishCommand()); + + /* + if (status == EMBER_ZCL_STATUS_SUCCESS) { - uint8_t * length; - emberAfPutInt16uInResp(ZCL_THERMOSTAT_CLUSTER_ID); - length = &appResponseData[appResponseLength]; - emberAfPutInt8uInResp(0); // temporary length - emberAfPutInt16sInResp(entry.occupiedCoolingSetpointValue); - *length += 2; - if (entry.hasOccupiedHeatingSetpointValue) + // The transition time is returned in seconds in the regular version of the + // command and tenths of a second in the enhanced version. + emberAfPutInt16uInResp( + static_cast(enhanced ? entry.transitionTime * 10 + entry.transitionTime100ms : entry.transitionTime)); + #ifdef EMBER_AF_PLUGIN_SCENES_NAME_SUPPORT + emberAfPutStringInResp(entry.name); + #else + emberAfPutInt8uInResp(0); // name length + #endif + #ifdef ZCL_USING_ON_OFF_CLUSTER_SERVER + if (entry.hasOnOffValue) + { + emberAfPutInt16uInResp(ZCL_ON_OFF_CLUSTER_ID); + emberAfPutInt8uInResp(1); // length + emberAfPutInt8uInResp(entry.onOffValue); + } + #endif + #ifdef ZCL_USING_LEVEL_CONTROL_CLUSTER_SERVER + if (entry.hasCurrentLevelValue) { - emberAfPutInt16sInResp(entry.occupiedHeatingSetpointValue); + emberAfPutInt16uInResp(ZCL_LEVEL_CONTROL_CLUSTER_ID); + emberAfPutInt8uInResp(1); // length + emberAfPutInt8uInResp(entry.currentLevelValue); + } + #endif + #ifdef ZCL_USING_THERMOSTAT_CLUSTER_SERVER + if (entry.hasOccupiedCoolingSetpointValue) + { + uint8_t * length; + emberAfPutInt16uInResp(ZCL_THERMOSTAT_CLUSTER_ID); + length = &appResponseData[appResponseLength]; + emberAfPutInt8uInResp(0); // temporary length + emberAfPutInt16sInResp(entry.occupiedCoolingSetpointValue); *length += 2; - if (entry.hasSystemModeValue) + if (entry.hasOccupiedHeatingSetpointValue) { - emberAfPutInt8uInResp(entry.systemModeValue); - (*length)++; + emberAfPutInt16sInResp(entry.occupiedHeatingSetpointValue); + *length += 2; + if (entry.hasSystemModeValue) + { + emberAfPutInt8uInResp(entry.systemModeValue); + (*length)++; + } } } - } -#endif -#ifdef ZCL_USING_COLOR_CONTROL_CLUSTER_SERVER - if (entry.hasCurrentXValue) - { - uint8_t * length; - emberAfPutInt16uInResp(ZCL_COLOR_CONTROL_CLUSTER_ID); - length = &appResponseData[appResponseLength]; - emberAfPutInt8uInResp(0); // temporary length - emberAfPutInt16uInResp(entry.currentXValue); - *length = static_cast(*length + 2); - if (entry.hasCurrentYValue) + #endif + #ifdef ZCL_USING_COLOR_CONTROL_CLUSTER_SERVER + if (entry.hasCurrentXValue) { - emberAfPutInt16uInResp(entry.currentYValue); + uint8_t * length; + emberAfPutInt16uInResp(ZCL_COLOR_CONTROL_CLUSTER_ID); + length = &appResponseData[appResponseLength]; + emberAfPutInt8uInResp(0); // temporary length + emberAfPutInt16uInResp(entry.currentXValue); *length = static_cast(*length + 2); - if (enhanced) + if (entry.hasCurrentYValue) { - if (entry.hasEnhancedCurrentHueValue) + emberAfPutInt16uInResp(entry.currentYValue); + *length = static_cast(*length + 2); + if (enhanced) { - emberAfPutInt16uInResp(entry.enhancedCurrentHueValue); - *length = static_cast(*length + 2); - if (entry.hasCurrentSaturationValue) + if (entry.hasEnhancedCurrentHueValue) { - emberAfPutInt8uInResp(entry.currentSaturationValue); - (*length)++; - if (entry.hasColorLoopActiveValue) + emberAfPutInt16uInResp(entry.enhancedCurrentHueValue); + *length = static_cast(*length + 2); + if (entry.hasCurrentSaturationValue) { - emberAfPutInt8uInResp(entry.colorLoopActiveValue); + emberAfPutInt8uInResp(entry.currentSaturationValue); (*length)++; - if (entry.hasColorLoopDirectionValue) + if (entry.hasColorLoopActiveValue) { - emberAfPutInt8uInResp(entry.colorLoopDirectionValue); + emberAfPutInt8uInResp(entry.colorLoopActiveValue); (*length)++; - if (entry.hasColorLoopTimeValue) + if (entry.hasColorLoopDirectionValue) { - emberAfPutInt16uInResp(entry.colorLoopTimeValue); - *length = static_cast(*length + 2); - if (entry.hasColorTemperatureMiredsValue) + emberAfPutInt8uInResp(entry.colorLoopDirectionValue); + (*length)++; + if (entry.hasColorLoopTimeValue) { - emberAfPutInt16uInResp(entry.colorTemperatureMiredsValue); + emberAfPutInt16uInResp(entry.colorLoopTimeValue); *length = static_cast(*length + 2); + if (entry.hasColorTemperatureMiredsValue) + { + emberAfPutInt16uInResp(entry.colorTemperatureMiredsValue); + *length = static_cast(*length + 2); + } } } } @@ -1117,33 +1263,32 @@ bool emberAfPluginScenesServerParseViewScene(const EmberAfClusterCommand * cmd, } } } - } -#endif // ZCL_USING_COLOR_CONTROL_CLUSTER_SERVER -#ifdef ZCL_USING_DOOR_LOCK_CLUSTER_SERVER - if (entry.hasLockStateValue) - { - emberAfPutInt16uInResp(ZCL_DOOR_LOCK_CLUSTER_ID); - emberAfPutInt8uInResp(1); // length - emberAfPutInt8uInResp(entry.lockStateValue); - } -#endif -#ifdef ZCL_USING_WINDOW_COVERING_CLUSTER_SERVER - if (entry.hasCurrentPositionLiftPercentageValue) - { - uint8_t * length; - emberAfPutInt16uInResp(ZCL_WINDOW_COVERING_CLUSTER_ID); - length = &appResponseData[appResponseLength]; - emberAfPutInt8uInResp(0); // temporary length - emberAfPutInt8uInResp(entry.currentPositionLiftPercentageValue); - (*length)++; - if (entry.hasCurrentPositionTiltPercentageValue) + #endif // ZCL_USING_COLOR_CONTROL_CLUSTER_SERVER + #ifdef ZCL_USING_DOOR_LOCK_CLUSTER_SERVER + if (entry.hasLockStateValue) + { + emberAfPutInt16uInResp(ZCL_DOOR_LOCK_CLUSTER_ID); + emberAfPutInt8uInResp(1); // length + emberAfPutInt8uInResp(entry.lockStateValue); + } + #endif + #ifdef ZCL_USING_WINDOW_COVERING_CLUSTER_SERVER + if (entry.hasCurrentPositionLiftPercentageValue) { - emberAfPutInt8uInResp(entry.currentPositionTiltPercentageValue); + uint8_t * length; + emberAfPutInt16uInResp(ZCL_WINDOW_COVERING_CLUSTER_ID); + length = &appResponseData[appResponseLength]; + emberAfPutInt8uInResp(0); // temporary length + emberAfPutInt8uInResp(entry.currentPositionLiftPercentageValue); (*length)++; + if (entry.hasCurrentPositionTiltPercentageValue) + { + emberAfPutInt8uInResp(entry.currentPositionTiltPercentageValue); + (*length)++; + } } + #endif } -#endif - } // View Scene commands are only responded to when they are addressed to a // single device. @@ -1156,6 +1301,13 @@ bool emberAfPluginScenesServerParseViewScene(const EmberAfClusterCommand * cmd, { emberAfScenesClusterPrintln("Scenes: failed to send %s response: 0x%x", "view_scene", sendStatus); } + */ + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Failed to encode response command."); + } return true; } diff --git a/src/app/clusters/scenes/scenes.h b/src/app/clusters/scenes/scenes.h index 2f4fef35be4cfa..6b1e8f48728df7 100644 --- a/src/app/clusters/scenes/scenes.h +++ b/src/app/clusters/scenes/scenes.h @@ -39,6 +39,7 @@ #pragma once +#include #include #include @@ -79,9 +80,11 @@ extern EmberAfSceneTableEntry emberAfPluginScenesServerSceneTable[]; #define emberAfPluginScenesServerDecrNumSceneEntriesInUse() (--emberAfPluginScenesServerEntriesInUse) #endif // Use tokens -bool emberAfPluginScenesServerParseAddScene(const EmberAfClusterCommand * cmd, chip::GroupId groupId, uint8_t sceneId, - uint16_t transitionTime, uint8_t * sceneName, uint8_t * extensionFieldSets); -bool emberAfPluginScenesServerParseViewScene(const EmberAfClusterCommand * cmd, chip::GroupId groupId, uint8_t sceneId); +bool emberAfPluginScenesServerParseAddScene(chip::app::Command * commandObj, const EmberAfClusterCommand * cmd, + chip::GroupId groupId, uint8_t sceneId, uint16_t transitionTime, uint8_t * sceneName, + uint8_t * extensionFieldSets); +bool emberAfPluginScenesServerParseViewScene(chip::app::Command * commandObj, const EmberAfClusterCommand * cmd, + chip::GroupId groupId, uint8_t sceneId); /** @brief Scenes Cluster Recall Saved Scene * diff --git a/src/app/clusters/zll-scenes-server/zll-scenes-server.c b/src/app/clusters/zll-scenes-server/zll-scenes-server.c index a1fd935f2f2293..63a05e0db5603d 100644 --- a/src/app/clusters/zll-scenes-server/zll-scenes-server.c +++ b/src/app/clusters/zll-scenes-server/zll-scenes-server.c @@ -73,9 +73,9 @@ bool emberAfScenesClusterEnhancedViewSceneCallback(chip::app::Command * commandO bool emberAfScenesClusterCopySceneCallback(chip::app::Command * commandObj, uint8_t mode, uint16_t groupIdFrom, uint8_t sceneIdFrom, uint16_t groupIdTo, uint8_t sceneIdTo) { - EmberStatus sendStatus; - EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_FIELD; - bool copyAllScenes = (mode & ZCL_SCENES_CLUSTER_MODE_COPY_ALL_SCENES_MASK); + EmberStatus sendStatus = EMBER_SUCCESS; + EmberAfStatus status = EMBER_ZCL_STATUS_INVALID_FIELD; + bool copyAllScenes = (mode & ZCL_SCENES_CLUSTER_MODE_COPY_ALL_SCENES_MASK); uint8_t i; emberAfScenesClusterPrintln("RX: CopyScene 0x%x, 0x%2x, 0x%x, 0x%2x, 0x%x", mode, groupIdFrom, sceneIdFrom, groupIdTo, From 6c1c96c7c725147d817a61fcbab3321f1c537726 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Tue, 11 May 2021 02:31:59 +0800 Subject: [PATCH 15/17] Disable IM dispatch for Python since Python script does not dispatch ZCL commands before --- src/app/chip_data_model.gni | 10 ++++++++-- src/controller/python/BUILD.gn | 1 + .../python/chip/interaction_model/Delegate.cpp | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 2ad90d84082170..e7fd87b82159d5 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -49,6 +49,10 @@ template("chip_data_model") { } } + _use_default_im_dispatch = + !defined(invoker.use_default_im_dispatch) || + invoker.use_default_im_dispatch + _use_default_client_callbacks = defined(invoker.use_default_client_callbacks) && invoker.use_default_client_callbacks @@ -108,7 +112,6 @@ template("chip_data_model") { "${_app_root}/util/process-cluster-message.cpp", "${_app_root}/util/process-global-message.cpp", "${_app_root}/util/util.cpp", - "${invoker.zap_pregenerated_dir}/IMClusterCommandHandler.cpp", ] if (defined(invoker.cluster_sources)) { @@ -146,13 +149,16 @@ template("chip_data_model") { "${invoker.zap_pregenerated_dir}/CHIPClusters.cpp", "${invoker.zap_pregenerated_dir}/CHIPClusters.h", "${invoker.zap_pregenerated_dir}/attribute-size.cpp", - "${invoker.zap_pregenerated_dir}/call-command-handler.cpp", "${invoker.zap_pregenerated_dir}/callback-stub.cpp", ] if (_use_default_client_callbacks) { sources += [ "${invoker.zap_pregenerated_dir}/CHIPClientCallbacks.cpp" ] } + + if (_use_default_im_dispatch) { + sources += [ "${invoker.zap_pregenerated_dir}/IMClusterCommandHandler.cpp" ] + } } if (!defined(public_deps)) { diff --git a/src/controller/python/BUILD.gn b/src/controller/python/BUILD.gn index af6df8801206b4..e769833853c993 100644 --- a/src/controller/python/BUILD.gn +++ b/src/controller/python/BUILD.gn @@ -37,6 +37,7 @@ chip_data_model("python_data_model") { zap_pregenerated_dir = "gen" use_default_client_callbacks = true + use_default_im_dispatch = false } shared_library("ChipDeviceCtrl") { diff --git a/src/controller/python/chip/interaction_model/Delegate.cpp b/src/controller/python/chip/interaction_model/Delegate.cpp index 37e869be25f611..fe27e9abdac048 100644 --- a/src/controller/python/chip/interaction_model/Delegate.cpp +++ b/src/controller/python/chip/interaction_model/Delegate.cpp @@ -15,6 +15,9 @@ * limitations under the License. */ +#include + +#include #include #include @@ -22,6 +25,21 @@ using namespace chip::app; namespace chip { + +namespace app { + +void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId, + chip::TLV::TLVReader & aReader, Command * apCommandObj) +{ + ChipLogDetail(Controller, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId, + aCommandId, aEndPointId); + ChipLogError( + Controller, + "Default DispatchSingleClusterCommand is called, this should be replaced by actual dispatched for cluster commands"); +} + +} // namespace app + namespace Controller { PythonInteractionModelDelegate gPythonInteractionModelDelegate; From 66a4bab82e9eb2af6dd49011c29f7ea2566df1a7 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Tue, 11 May 2021 02:29:59 +0000 Subject: [PATCH 16/17] Restyled by gn --- src/app/chip_data_model.gni | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index e7fd87b82159d5..fc1f1d78b3e7ac 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -49,9 +49,8 @@ template("chip_data_model") { } } - _use_default_im_dispatch = - !defined(invoker.use_default_im_dispatch) || - invoker.use_default_im_dispatch + _use_default_im_dispatch = !defined(invoker.use_default_im_dispatch) || + invoker.use_default_im_dispatch _use_default_client_callbacks = defined(invoker.use_default_client_callbacks) && @@ -157,7 +156,8 @@ template("chip_data_model") { } if (_use_default_im_dispatch) { - sources += [ "${invoker.zap_pregenerated_dir}/IMClusterCommandHandler.cpp" ] + sources += + [ "${invoker.zap_pregenerated_dir}/IMClusterCommandHandler.cpp" ] } } From 7808ceae3ebcd9b663afacb9d130a76f67db280b Mon Sep 17 00:00:00 2001 From: Song Guo Date: Tue, 11 May 2021 14:04:09 +0800 Subject: [PATCH 17/17] Fix chip-tool init routine for sending cluster commands --- examples/chip-tool/commands/clusters/ModelCommand.h | 2 +- examples/chip-tool/commands/common/Command.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/chip-tool/commands/clusters/ModelCommand.h b/examples/chip-tool/commands/clusters/ModelCommand.h index cf13212965d07b..8a0e237c06720e 100644 --- a/examples/chip-tool/commands/clusters/ModelCommand.h +++ b/examples/chip-tool/commands/clusters/ModelCommand.h @@ -40,7 +40,7 @@ class ModelCommand : public Command virtual CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endPointId) = 0; private: - ChipDeviceCommissioner mCommissioner; + ChipDeviceController mCommissioner; ChipDevice * mDevice; uint8_t mEndPointId; }; diff --git a/examples/chip-tool/commands/common/Command.h b/examples/chip-tool/commands/common/Command.h index 953ff7205da870..8fa8e87b97a0b2 100644 --- a/examples/chip-tool/commands/common/Command.h +++ b/examples/chip-tool/commands/common/Command.h @@ -74,6 +74,7 @@ class Command { public: using ChipDeviceCommissioner = ::chip::Controller::DeviceCommissioner; + using ChipDeviceController = ::chip::Controller::DeviceController; using ChipSerializedDevice = ::chip::Controller::SerializedDevice; using ChipDevice = ::chip::Controller::Device; using PeerAddress = ::chip::Transport::PeerAddress;