From 9cd22c120694201d1a168fd08d0629d290dfa39f Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 8 Oct 2021 01:02:03 -0400 Subject: [PATCH] Switch server-side command decoding to using the cluster-objects infrastructure (#10296) * Switch command decoding to using the cluster-objects infrastructure. For now we are still passing the existing arguments to cluster callbacks, so we don't need to update cluster implementations as part of this change. The change to how we encode CHAR_STRING command arguments is needed because the new setup expects to decode them as TLV UTF-8 strings, not TLV octet strings. * Regenerate generated files --- .../esp32/main/CMakeLists.txt | 2 + examples/bridge-app/esp32/main/CMakeLists.txt | 1 + examples/lighting-app/mbed/CMakeLists.txt | 1 + examples/lighting-app/telink/CMakeLists.txt | 1 + examples/lock-app/esp32/main/CMakeLists.txt | 2 + examples/lock-app/mbed/CMakeLists.txt | 1 + .../esp32/main/CMakeLists.txt | 1 + src/app/chip_data_model.cmake | 1 + .../im_command_handler_cluster_commands.zapt | 34 +- .../templates/app/CHIPClusters-src.zapt | 7 + .../app/im-cluster-command-handler.zapt | 15 +- .../zap-generated/IMClusterCommandHandler.cpp | 6635 ++--------------- .../zap-generated/IMClusterCommandHandler.cpp | 2111 +----- .../zap-generated/CHIPClusters.cpp | 57 +- .../zap-generated/IMClusterCommandHandler.cpp | 7 +- .../zap-generated/CHIPClusters.cpp | 1 + .../zap-generated/IMClusterCommandHandler.cpp | 3655 +-------- .../zap-generated/IMClusterCommandHandler.cpp | 1610 +--- .../zap-generated/IMClusterCommandHandler.cpp | 668 +- .../zap-generated/CHIPClusters.cpp | 4 +- .../zap-generated/IMClusterCommandHandler.cpp | 7 +- .../pump-app/zap-generated/CHIPClusters.cpp | 1 + .../zap-generated/IMClusterCommandHandler.cpp | 2055 +---- .../zap-generated/CHIPClusters.cpp | 1 + .../zap-generated/IMClusterCommandHandler.cpp | 1570 +--- .../zap-generated/IMClusterCommandHandler.cpp | 1440 +--- .../zap-generated/IMClusterCommandHandler.cpp | 6252 ++-------------- .../tv-app/zap-generated/CHIPClusters.cpp | 7 +- .../zap-generated/IMClusterCommandHandler.cpp | 5485 +++----------- .../zap-generated/IMClusterCommandHandler.cpp | 5999 ++------------- .../zap-generated/IMClusterCommandHandler.cpp | 1765 +---- 31 files changed, 4209 insertions(+), 35187 deletions(-) diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 9106669c7d3038..0c065f96302331 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -29,7 +29,9 @@ set(PRIV_INCLUDE_DIRS_LIST set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/all-clusters-app/zap-generated" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" diff --git a/examples/bridge-app/esp32/main/CMakeLists.txt b/examples/bridge-app/esp32/main/CMakeLists.txt index 461555fbe4af92..083b0253c031e5 100644 --- a/examples/bridge-app/esp32/main/CMakeLists.txt +++ b/examples/bridge-app/esp32/main/CMakeLists.txt @@ -25,6 +25,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/bridge-app/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" diff --git a/examples/lighting-app/mbed/CMakeLists.txt b/examples/lighting-app/mbed/CMakeLists.txt index 26844ff08c8638..a0876b2b710627 100644 --- a/examples/lighting-app/mbed/CMakeLists.txt +++ b/examples/lighting-app/mbed/CMakeLists.txt @@ -50,6 +50,7 @@ target_sources(${APP_TARGET} PRIVATE ${GEN_DIR}/lighting-app/zap-generated/IMClusterCommandHandler.cpp ${MBED_COMMON}/util/LEDWidget.cpp ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp + ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp ${CHIP_ROOT}/src/app/util/DataModelHandler.cpp ${CHIP_ROOT}/src/app/reporting/reporting-default-configuration.cpp ${CHIP_ROOT}/src/app/reporting/reporting.cpp diff --git a/examples/lighting-app/telink/CMakeLists.txt b/examples/lighting-app/telink/CMakeLists.txt index ab6f175545ae18..fd4f9e65d9857c 100644 --- a/examples/lighting-app/telink/CMakeLists.txt +++ b/examples/lighting-app/telink/CMakeLists.txt @@ -52,6 +52,7 @@ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/ButtonManager.cpp ${TELINK_COMMON}/util/src/ThreadUtil.cpp ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp + ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp ${CHIP_ROOT}/src/app/util/DataModelHandler.cpp ${CHIP_ROOT}/src/app/reporting/reporting-default-configuration.cpp ${CHIP_ROOT}/src/app/reporting/reporting.cpp diff --git a/examples/lock-app/esp32/main/CMakeLists.txt b/examples/lock-app/esp32/main/CMakeLists.txt index ee494f4d275c62..43c0b0bbde20ec 100644 --- a/examples/lock-app/esp32/main/CMakeLists.txt +++ b/examples/lock-app/esp32/main/CMakeLists.txt @@ -36,6 +36,7 @@ idf_component_register(INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/../../common/pigweed" "${CMAKE_SOURCE_DIR}/../../common/pigweed/esp32" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/lock-app/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" @@ -128,6 +129,7 @@ idf_component_register(PRIV_INCLUDE_DIRS SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/lock-app/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" diff --git a/examples/lock-app/mbed/CMakeLists.txt b/examples/lock-app/mbed/CMakeLists.txt index 01ead28166d644..47540781607623 100644 --- a/examples/lock-app/mbed/CMakeLists.txt +++ b/examples/lock-app/mbed/CMakeLists.txt @@ -50,6 +50,7 @@ target_sources(${APP_TARGET} PRIVATE ${MBED_COMMON}/util/LEDWidget.cpp ${CHIP_ROOT}/src/app/util/DataModelHandler.cpp ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp + ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp ${CHIP_ROOT}/src/app/reporting/reporting-default-configuration.cpp ${CHIP_ROOT}/src/app/reporting/reporting.cpp ${CHIP_ROOT}/src/app/util/af-event.cpp diff --git a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt index 5fb4f42057ac3c..cb984dee26eada 100644 --- a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt +++ b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt @@ -27,6 +27,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/temperature-measurement-app/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" diff --git a/src/app/chip_data_model.cmake b/src/app/chip_data_model.cmake index 9a49ed854899c6..284ada3631dbba 100644 --- a/src/app/chip_data_model.cmake +++ b/src/app/chip_data_model.cmake @@ -72,6 +72,7 @@ function(chip_configure_data_model APP_TARGET) target_sources(${APP_TARGET} PRIVATE ${CHIP_APP_BASE_DIR}/../../zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp + ${CHIP_APP_BASE_DIR}/../../zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp ${CHIP_APP_BASE_DIR}/reporting/reporting-default-configuration.cpp ${CHIP_APP_BASE_DIR}/reporting/reporting.cpp ${CHIP_APP_BASE_DIR}/util/af-event.cpp 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 123ec9a2e2b6e3..2e64bc14f3f9f8 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,6 +1,34 @@ {{#if (isServer parent.side)}} Commands::{{asUpperCamelCase name}}::DecodableType commandData; +TLVError = DataModel::Decode(aDataTlv, commandData); +if (TLVError == CHIP_NO_ERROR) { +{{! A few things going on here: + 1) isArray should override other type checks, because you can test true for + both isArray and other things. + 2) Enums are enum classes in the struct but raw integers in the args. Need + to use to_underlying for them. + 3) Char strings are Span in the struct but uint8_t* in the args. + Do the same broken casting we used to do. Need to stop using the args! + 4) Lists are DecodableList<> in the struct but the args expect + uint8_t*. Just pass nullptr and convert the relevant commands to + using the struct argument later. They don't work properly right + now anyway. +}} +wasHandled = emberAf{{asUpperCamelCase parent.name}}Cluster{{asUpperCamelCase name}}Callback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, {{#zcl_command_arguments}}{{#if isArray}} +nullptr +{{else}} +{{#if_is_enum type}} +to_underlying(commandData.{{asLowerCamelCase label}}) +{{else}} +{{#if (isCharString type)}} +const_cast(Uint8::from_const_char(commandData.{{asLowerCamelCase label}}.data())) +{{else}} +commandData.{{asLowerCamelCase label}} {{/if}} +{{/if_is_enum}} +{{/if}},{{/zcl_command_arguments}} commandData); +} +{{else}} {{#if (zcl_command_arguments_count this.id)}} expectArgumentCount = {{ zcl_command_arguments_count this.id }}; {{#zcl_command_arguments}} @@ -74,12 +102,8 @@ if (CHIP_END_OF_TLV == TLVError) if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && {{zcl_command_arguments_count this.id}} == validArgumentCount) { {{/if}} -{{! TODO: if the command has a response command defined, put its id in the command path. }} -{{#if (isServer parent.side)}} -wasHandled = emberAf{{asUpperCamelCase parent.name}}Cluster{{asUpperCamelCase name}}Callback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, {{#zcl_command_arguments}}{{#if (isCharString type)}}const_cast({{asSymbol label}}){{else}}{{asSymbol label}}{{/if}},{{/zcl_command_arguments}} commandData); -{{else}} wasHandled = emberAf{{asUpperCamelCase parent.name}}Cluster{{asUpperCamelCase name}}Callback(aCommandPath.mEndpointId, apCommandObj{{#zcl_command_arguments}}, {{#if (isCharString type)}}const_cast({{asSymbol label}}){{else}}{{asSymbol label}}{{/if}}{{/zcl_command_arguments}}); -{{/if}} {{#if (zcl_command_arguments_count this.id)}} } {{/if}} +{{/if}} diff --git a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt index 21f43f7f6d5ab8..198958a365e6a5 100644 --- a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -58,7 +59,13 @@ CHIP_ERROR {{asUpperCamelCase clusterName}}Cluster::{{asUpperCamelCase name}}(Ca VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); {{/first}} // {{asLowerCamelCase label}}: {{asLowerCamelCase type}} +{{#if (isCharString type)}} + {{! The server expects to get a UTF-8 string, but we have ByteSpan. Do + some conversion to get the right thing to happen. }} + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), Span(Uint8::to_const_char({{asLowerCamelCase label}}.data()), {{asLowerCamelCase label}}.size()))); +{{else}} SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), {{asLowerCamelCase label}})); +{{/if}} {{else}} // Command takes no arguments. {{/chip_cluster_command_arguments}} 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 31103b23607077..be8b00cbff9b1c 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 @@ -9,8 +9,9 @@ #include #include #include "app/util/util.h" - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -44,10 +45,12 @@ void Dispatch{{asUpperCamelCase side}}Command({{#if (isServer side)}}CommandHand // 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; + {{#unless (isServer parent.side)}} CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; uint32_t validArgumentCount = 0; uint32_t expectArgumentCount = 0; uint32_t currentDecodeTagId = 0; + {{/unless}} bool wasHandled = false; { switch (aCommandPath.mCommandId) @@ -66,15 +69,19 @@ void Dispatch{{asUpperCamelCase side}}Command({{#if (isServer side)}}CommandHand } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError {{#unless (isServer parent.side)}}|| CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount{{/unless}} || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + {{#if (isServer parent.side)}} + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + {{else}} ChipLogProgress(Zcl, "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); // A command with no arguments would never write currentDecodeTagId. If // progress logging is also disabled, it would look unused. Silence that // warning. UNUSED_VAR(currentDecodeTagId); + {{/if}} } {{/last}} {{else}} @@ -95,8 +102,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { {{#chip_server_clusters}} @@ -117,8 +122,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/all-clusters-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/all-clusters-app/zap-generated/IMClusterCommandHandler.cpp index e2f1cefdf7e2d6..64f41a4b4cb9d1 100644 --- a/zzz_generated/all-clusters-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/all-clusters-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,80 +121,29 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::BarrierControlGoToPercent::Id: { Commands::BarrierControlGoToPercent::DecodableType commandData; - expectArgumentCount = 1; - uint8_t percentOpen; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(percentOpen); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfBarrierControlClusterBarrierControlGoToPercentCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, percentOpen, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.percentOpen, commandData); } break; } case Commands::BarrierControlStop::Id: { Commands::BarrierControlStop::DecodableType commandData; - - wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -331,18 +154,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -365,156 +181,30 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Bind::Id: { Commands::Bind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(nodeId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); } break; } case Commands::Unbind::Id: { Commands::Unbind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(nodeId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); } break; } @@ -526,18 +216,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -551,1456 +234,221 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ColorLoopSet::Id: { Commands::ColorLoopSet::DecodableType commandData; - expectArgumentCount = 7; - uint8_t updateFlags; - uint8_t action; - uint8_t direction; - uint16_t time; - uint16_t startHue; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateFlags); - break; - case 1: - TLVUnpackError = aDataTlv.Get(action); - break; - case 2: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 3: - TLVUnpackError = aDataTlv.Get(time); - break; - case 4: - TLVUnpackError = aDataTlv.Get(startHue); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 6: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterColorLoopSetCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - updateFlags, action, direction, time, startHue, - optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterColorLoopSetCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateFlags, + to_underlying(commandData.action), to_underlying(commandData.direction), commandData.time, commandData.startHue, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::EnhancedMoveHue::Id: { Commands::EnhancedMoveHue::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint16_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterEnhancedMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterEnhancedMoveHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::EnhancedMoveToHue::Id: { Commands::EnhancedMoveToHue::DecodableType commandData; - expectArgumentCount = 5; - uint16_t enhancedHue; - uint8_t direction; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(enhancedHue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterEnhancedMoveToHueCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, enhancedHue, direction, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.enhancedHue, + to_underlying(commandData.direction), commandData.transitionTime, commandData.optionsMask, + commandData.optionsOverride, commandData); } break; } case Commands::EnhancedMoveToHueAndSaturation::Id: { Commands::EnhancedMoveToHueAndSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint16_t enhancedHue; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(enhancedHue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterEnhancedMoveToHueAndSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, enhancedHue, saturation, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.enhancedHue, commandData.saturation, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::EnhancedStepHue::Id: { Commands::EnhancedStepHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint16_t stepSize; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterEnhancedStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterEnhancedStepHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveColor::Id: { Commands::MoveColor::DecodableType commandData; - expectArgumentCount = 4; - int16_t rateX; - int16_t rateY; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(rateX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rateY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - rateX, rateY, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rateX, commandData.rateY, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveColorTemperature::Id: { Commands::MoveColorTemperature::DecodableType commandData; - expectArgumentCount = 6; - uint8_t moveMode; - uint16_t rate; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, rate, colorTemperatureMinimum, - colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, commandData.optionsMask, + commandData.optionsOverride, commandData); } break; } case Commands::MoveHue::Id: { Commands::MoveHue::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveSaturation::Id: { Commands::MoveSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterMoveSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColor::Id: { Commands::MoveToColor::DecodableType commandData; - expectArgumentCount = 5; - uint16_t colorX; - uint16_t colorY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(colorY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveToColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - colorX, colorY, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveToColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorX, commandData.colorY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColorTemperature::Id: { Commands::MoveToColorTemperature::DecodableType commandData; - expectArgumentCount = 4; - uint16_t colorTemperature; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorTemperature); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, colorTemperature, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorTemperature, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHue::Id: { Commands::MoveToHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t direction; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterMoveToHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, - direction, transitionTime, optionsMask, optionsOverride, - commandData); + wasHandled = emberAfColorControlClusterMoveToHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, to_underlying(commandData.direction), + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHueAndSaturation::Id: { Commands::MoveToHueAndSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToHueAndSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, saturation, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, commandData.saturation, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToSaturation::Id: { Commands::MoveToSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, saturation, transitionTime, optionsMask, optionsOverride, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.saturation, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColor::Id: { Commands::StepColor::DecodableType commandData; - expectArgumentCount = 5; - int16_t stepX; - int16_t stepY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterStepColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepX, stepY, - transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.stepX, commandData.stepY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColorTemperature::Id: { Commands::StepColorTemperature::DecodableType commandData; - expectArgumentCount = 7; - uint8_t stepMode; - uint16_t stepSize; - uint16_t transitionTime; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 6: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStepColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, transitionTime, - colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepHue::Id: { Commands::StepHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfColorControlClusterStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, - stepSize, transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepSaturation::Id: { Commands::StepSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterStepSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StopMoveStep::Id: { Commands::StopMoveStep::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStopMoveStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionsMask, optionsOverride, commandData); + commandData.optionsMask, commandData.optionsOverride, + commandData); } break; } @@ -2012,18 +460,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -2037,81 +478,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -2123,18 +502,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -2148,1385 +520,246 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ClearAllPins::Id: { Commands::ClearAllPins::DecodableType commandData; - - wasHandled = - emberAfDoorLockClusterClearAllPinsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfDoorLockClusterClearAllPinsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::ClearAllRfids::Id: { Commands::ClearAllRfids::DecodableType commandData; - - wasHandled = - emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::ClearHolidaySchedule::Id: { Commands::ClearHolidaySchedule::DecodableType commandData; - expectArgumentCount = 1; - uint8_t scheduleId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterClearHolidayScheduleCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, scheduleId, commandData); + wasHandled = emberAfDoorLockClusterClearHolidayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData); } break; } case Commands::ClearPin::Id: { Commands::ClearPin::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::ClearRfid::Id: { Commands::ClearRfid::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::ClearWeekdaySchedule::Id: { Commands::ClearWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterClearWeekdayScheduleCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, userId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::ClearYeardaySchedule::Id: { Commands::ClearYeardaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterClearYeardayScheduleCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, userId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::GetHolidaySchedule::Id: { Commands::GetHolidaySchedule::DecodableType commandData; - expectArgumentCount = 1; - uint8_t scheduleId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterGetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, commandData); + commandData.scheduleId, commandData); } break; } case Commands::GetLogRecord::Id: { Commands::GetLogRecord::DecodableType commandData; - expectArgumentCount = 1; - uint16_t logIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(logIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterGetLogRecordCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - logIndex, commandData); + commandData.logIndex, commandData); } break; } case Commands::GetPin::Id: { Commands::GetPin::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = - emberAfDoorLockClusterGetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, commandData); + wasHandled = emberAfDoorLockClusterGetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetRfid::Id: { Commands::GetRfid::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetUserType::Id: { Commands::GetUserType::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetWeekdaySchedule::Id: { Commands::GetWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterGetWeekdayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, commandData); + wasHandled = emberAfDoorLockClusterGetWeekdayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::GetYeardaySchedule::Id: { - Commands::GetYeardaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterGetYeardayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, commandData); - } - break; - } - case Commands::LockDoor::Id: { - Commands::LockDoor::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan PIN; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(PIN); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + Commands::GetYeardaySchedule::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfDoorLockClusterGetYeardayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + break; + } + case Commands::LockDoor::Id: { + Commands::LockDoor::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfDoorLockClusterLockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, PIN, commandData); + wasHandled = emberAfDoorLockClusterLockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.pin, commandData); } break; } case Commands::SetHolidaySchedule::Id: { Commands::SetHolidaySchedule::DecodableType commandData; - expectArgumentCount = 4; - uint8_t scheduleId; - uint32_t localStartTime; - uint32_t localEndTime; - uint8_t operatingModeDuringHoliday; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(localStartTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(localEndTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, localStartTime, localEndTime, - operatingModeDuringHoliday, commandData); + wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.localStartTime, + commandData.localEndTime, commandData.operatingModeDuringHoliday, commandData); } break; } case Commands::SetPin::Id: { Commands::SetPin::DecodableType commandData; - expectArgumentCount = 4; - uint16_t userId; - uint8_t userStatus; - uint8_t userType; - chip::ByteSpan pin; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userStatus); - break; - case 2: - TLVUnpackError = aDataTlv.Get(userType); - break; - case 3: - TLVUnpackError = aDataTlv.Get(pin); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userStatus, userType, pin, commandData); + wasHandled = emberAfDoorLockClusterSetPinCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.userId, to_underlying(commandData.userStatus), + to_underlying(commandData.userType), commandData.pin, commandData); } break; } case Commands::SetRfid::Id: { Commands::SetRfid::DecodableType commandData; - expectArgumentCount = 4; - uint16_t userId; - uint8_t userStatus; - uint8_t userType; - chip::ByteSpan id; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userStatus); - break; - case 2: - TLVUnpackError = aDataTlv.Get(userType); - break; - case 3: - TLVUnpackError = aDataTlv.Get(id); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userStatus, userType, id, commandData); + wasHandled = emberAfDoorLockClusterSetRfidCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.userId, to_underlying(commandData.userStatus), + to_underlying(commandData.userType), commandData.id, commandData); } break; } case Commands::SetUserType::Id: { Commands::SetUserType::DecodableType commandData; - expectArgumentCount = 2; - uint16_t userId; - uint8_t userType; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userType, commandData); + wasHandled = + emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, to_underlying(commandData.userType), commandData); } break; } case Commands::SetWeekdaySchedule::Id: { Commands::SetWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 7; - uint8_t scheduleId; - uint16_t userId; - uint8_t daysMask; - uint8_t startHour; - uint8_t startMinute; - uint8_t endHour; - uint8_t endMinute; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(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: - TLVUnpackError = aDataTlv.Get(startMinute); - break; - case 5: - TLVUnpackError = aDataTlv.Get(endHour); - break; - case 6: - TLVUnpackError = aDataTlv.Get(endMinute); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, daysMask, startHour, startMinute, - endHour, endMinute, commandData); + wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, + commandData.daysMask, commandData.startHour, commandData.startMinute, commandData.endHour, + commandData.endMinute, commandData); } break; } case Commands::SetYeardaySchedule::Id: { Commands::SetYeardaySchedule::DecodableType commandData; - expectArgumentCount = 4; - uint8_t scheduleId; - uint16_t userId; - uint32_t localStartTime; - uint32_t localEndTime; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(localStartTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(localEndTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfDoorLockClusterSetYeardayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, localStartTime, localEndTime, commandData); + wasHandled = emberAfDoorLockClusterSetYeardayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, + commandData.localStartTime, commandData.localEndTime, commandData); } break; } case Commands::UnlockDoor::Id: { Commands::UnlockDoor::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan PIN; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(PIN); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, PIN, - commandData); + wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.pin, commandData); } break; } case Commands::UnlockWithTimeout::Id: { Commands::UnlockWithTimeout::DecodableType commandData; - expectArgumentCount = 2; - uint16_t timeoutInSeconds; - chip::ByteSpan pin; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutInSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(pin); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - timeoutInSeconds, pin, commandData); + wasHandled = + emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.timeoutInSeconds, commandData.pin, commandData); } break; } @@ -3538,18 +771,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3563,20 +789,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetCounts::Id: { Commands::ResetCounts::DecodableType commandData; - - wasHandled = emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -3587,18 +812,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3612,161 +830,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -3778,18 +876,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3803,334 +894,70 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddGroup::Id: { Commands::AddGroup::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - const uint8_t * groupName; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(groupName); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - const_cast(groupName), commandData); + wasHandled = emberAfGroupsClusterAddGroupCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, + const_cast(Uint8::from_const_char(commandData.groupName.data())), commandData); } break; } case Commands::AddGroupIfIdentifying::Id: { Commands::AddGroupIfIdentifying::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - const uint8_t * groupName; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(groupName); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGroupsClusterAddGroupIfIdentifyingCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, const_cast(groupName), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, + const_cast(Uint8::from_const_char(commandData.groupName.data())), commandData); } break; } case Commands::GetGroupMembership::Id: { Commands::GetGroupMembership::DecodableType commandData; - expectArgumentCount = 2; - uint8_t groupCount; - /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupCount); - break; - case 1: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupCount, groupList, commandData); + commandData.groupCount, nullptr, commandData); } break; } case Commands::RemoveAllGroups::Id: { Commands::RemoveAllGroups::DecodableType commandData; - - wasHandled = - emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::RemoveGroup::Id: { Commands::RemoveGroup::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - commandData); + wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData); } break; } case Commands::ViewGroup::Id: { Commands::ViewGroup::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - commandData); + wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData); } break; } @@ -4142,18 +969,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4167,76 +987,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ZoneEnrollResponse::Id: { Commands::ZoneEnrollResponse::DecodableType commandData; - expectArgumentCount = 2; - uint8_t enrollResponseCode; - uint8_t zoneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(enrollResponseCode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(zoneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfIasZoneClusterZoneEnrollResponseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - enrollResponseCode, zoneId, commandData); + to_underlying(commandData.enrollResponseCode), + commandData.zoneId, commandData); } break; } @@ -4248,18 +1011,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4273,80 +1029,29 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Identify::Id: { Commands::Identify::DecodableType commandData; - expectArgumentCount = 1; - uint16_t identifyTime; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(identifyTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - identifyTime, commandData); + commandData.identifyTime, commandData); } break; } case Commands::IdentifyQuery::Id: { Commands::IdentifyQuery::DecodableType commandData; - - wasHandled = - emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -4357,18 +1062,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4382,502 +1080,96 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Move::Id: { Commands::Move::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevel::Id: { Commands::MoveToLevel::DecodableType commandData; - expectArgumentCount = 4; - uint8_t level; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.level, commandData.transitionTime, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevelWithOnOff::Id: { Commands::MoveToLevelWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t level; - uint16_t transitionTime; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.level, + commandData.transitionTime, commandData); } break; } case Commands::MoveWithOnOff::Id: { Commands::MoveWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t moveMode; - uint8_t rate; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, commandData); + to_underlying(commandData.moveMode), commandData.rate, + commandData); } break; } case Commands::Step::Id: { Commands::Step::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterStepCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StepWithOnOff::Id: { Commands::StepWithOnOff::DecodableType commandData; - expectArgumentCount = 3; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData); } break; } case Commands::Stop::Id: { Commands::Stop::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionMask, optionOverride, commandData); + wasHandled = + emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StopWithOnOff::Id: { Commands::StopWithOnOff::DecodableType commandData; - - wasHandled = - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -4888,18 +1180,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4913,19 +1198,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Sleep::Id: { Commands::Sleep::DecodableType commandData; - - wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -4936,18 +1220,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4961,624 +1238,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; - } - case Commands::DisableNetwork::Id: { - Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + } + case Commands::DisableNetwork::Id: { + Commands::DisableNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -5590,18 +1349,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5615,230 +1367,43 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ApplyUpdateRequest::Id: { Commands::ApplyUpdateRequest::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t newVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(newVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, newVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.newVersion, + commandData); } break; } case Commands::NotifyUpdateApplied::Id: { Commands::NotifyUpdateApplied::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t softwareVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, softwareVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.softwareVersion, + commandData); } break; } case Commands::QueryImage::Id: { Commands::QueryImage::DecodableType commandData; - expectArgumentCount = 8; - uint16_t vendorId; - uint16_t productId; - uint16_t hardwareVersion; - uint32_t softwareVersion; - uint8_t protocolsSupported; - const uint8_t * location; - bool requestorCanConsent; - chip::ByteSpan metadataForProvider; - bool argExists[8]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 8) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(vendorId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(productId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(hardwareVersion); - break; - case 3: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - case 4: - TLVUnpackError = aDataTlv.Get(protocolsSupported); - break; - case 5: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(location); - break; - case 6: - TLVUnpackError = aDataTlv.Get(requestorCanConsent); - break; - case 7: - TLVUnpackError = aDataTlv.Get(metadataForProvider); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, vendorId, productId, hardwareVersion, softwareVersion, - protocolsSupported, const_cast(location), requestorCanConsent, metadataForProvider, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.vendorId, commandData.productId, + commandData.hardwareVersion, commandData.softwareVersion, to_underlying(commandData.protocolsSupported), + const_cast(Uint8::from_const_char(commandData.location.data())), commandData.requestorCanConsent, + commandData.metadataForProvider, commandData); } break; } @@ -5850,18 +1415,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5875,31 +1433,36 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Off::Id: { Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::On::Id: { Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::Toggle::Id: { Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -5910,18 +1473,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5935,574 +1491,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -6514,18 +1596,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6539,471 +1614,81 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddScene::Id: { Commands::AddScene::DecodableType commandData; - expectArgumentCount = 5; - uint16_t groupId; - uint8_t sceneId; - uint16_t transitionTime; - const uint8_t * sceneName; - /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - break; - case 4: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfScenesClusterAddSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, transitionTime, const_cast(sceneName), - extensionFieldSets, commandData); + wasHandled = emberAfScenesClusterAddSceneCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, commandData.sceneId, + commandData.transitionTime, const_cast(Uint8::from_const_char(commandData.sceneName.data())), + nullptr, commandData); } break; } case Commands::GetSceneMembership::Id: { Commands::GetSceneMembership::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupId, commandData); + commandData.groupId, commandData); } break; } case Commands::RecallScene::Id: { Commands::RecallScene::DecodableType commandData; - expectArgumentCount = 3; - uint16_t groupId; - uint8_t sceneId; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, transitionTime, commandData); + wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, + commandData.transitionTime, commandData); } break; } case Commands::RemoveAllScenes::Id: { Commands::RemoveAllScenes::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupId, commandData); + commandData.groupId, commandData); } break; } case Commands::RemoveScene::Id: { Commands::RemoveScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } case Commands::StoreScene::Id: { Commands::StoreScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } case Commands::ViewScene::Id: { Commands::ViewScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } @@ -7015,18 +1700,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -7040,20 +1718,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetWatermarks::Id: { Commands::ResetWatermarks::DecodableType commandData; - - wasHandled = emberAfSoftwareDiagnosticsClusterResetWatermarksCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfSoftwareDiagnosticsClusterResetWatermarksCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -7064,18 +1741,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -7089,97 +1759,49 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Test::Id: { Commands::Test::DecodableType commandData; - - wasHandled = emberAfTestClusterClusterTestCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfTestClusterClusterTestCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::TestAddArguments::Id: { Commands::TestAddArguments::DecodableType commandData; - expectArgumentCount = 2; - uint8_t arg1; - uint8_t arg2; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(arg1); - break; - case 1: - TLVUnpackError = aDataTlv.Get(arg2); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfTestClusterClusterTestAddArgumentsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - arg1, arg2, commandData); + commandData.arg1, commandData.arg2, commandData); } break; } case Commands::TestNotHandled::Id: { Commands::TestNotHandled::DecodableType commandData; - - wasHandled = - emberAfTestClusterClusterTestNotHandledCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfTestClusterClusterTestNotHandledCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } case Commands::TestSpecific::Id: { Commands::TestSpecific::DecodableType commandData; - - wasHandled = - emberAfTestClusterClusterTestSpecificCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfTestClusterClusterTestSpecificCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -7190,18 +1812,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -7215,20 +1830,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetCounts::Id: { Commands::ResetCounts::DecodableType commandData; - - wasHandled = emberAfThreadNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfThreadNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -7239,18 +1853,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -7264,20 +1871,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetCounts::Id: { Commands::ResetCounts::DecodableType commandData; - - wasHandled = emberAfWiFiNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfWiFiNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -7288,18 +1894,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -7313,34 +1912,39 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::DownOrClose::Id: { Commands::DownOrClose::DecodableType commandData; - - wasHandled = - emberAfWindowCoveringClusterDownOrCloseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfWindowCoveringClusterDownOrCloseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } case Commands::StopMotion::Id: { Commands::StopMotion::DecodableType commandData; - - wasHandled = - emberAfWindowCoveringClusterStopMotionCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfWindowCoveringClusterStopMotionCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } case Commands::UpOrOpen::Id: { Commands::UpOrOpen::DecodableType commandData; - - wasHandled = - emberAfWindowCoveringClusterUpOrOpenCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfWindowCoveringClusterUpOrOpenCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -7351,18 +1955,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -7377,8 +1974,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -7460,8 +2055,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/bridge-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/bridge-app/zap-generated/IMClusterCommandHandler.cpp index 4395babe1c70e4..fb7cf4ac0cb7a0 100644 --- a/zzz_generated/bridge-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/bridge-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,81 +121,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -333,18 +145,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -358,161 +163,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -524,18 +209,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -549,502 +227,96 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Move::Id: { Commands::Move::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevel::Id: { Commands::MoveToLevel::DecodableType commandData; - expectArgumentCount = 4; - uint8_t level; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.level, commandData.transitionTime, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevelWithOnOff::Id: { Commands::MoveToLevelWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t level; - uint16_t transitionTime; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.level, + commandData.transitionTime, commandData); } break; } case Commands::MoveWithOnOff::Id: { Commands::MoveWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t moveMode; - uint8_t rate; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, commandData); + to_underlying(commandData.moveMode), commandData.rate, + commandData); } break; } case Commands::Step::Id: { Commands::Step::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterStepCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StepWithOnOff::Id: { Commands::StepWithOnOff::DecodableType commandData; - expectArgumentCount = 3; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData); } break; } case Commands::Stop::Id: { Commands::Stop::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionMask, optionOverride, commandData); + wasHandled = + emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StopWithOnOff::Id: { Commands::StopWithOnOff::DecodableType commandData; - - wasHandled = - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -1055,18 +327,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1080,624 +345,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -1709,18 +456,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1734,31 +474,36 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Off::Id: { Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::On::Id: { Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::Toggle::Id: { Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -1769,18 +514,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1794,574 +532,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -2373,18 +637,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -2399,8 +656,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -2431,8 +686,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp index b92fae292a54f7..4e9f3d4685ac03 100644 --- a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,9 @@ CHIP_ERROR AccountLoginCluster::GetSetupPIN(Callback::Cancelable * onSuccessCall VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // tempAccountIdentifier: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), tempAccountIdentifier)); + SuccessOrExit(err = writer->PutString( + TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(tempAccountIdentifier.data()), tempAccountIdentifier.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -109,9 +112,12 @@ CHIP_ERROR AccountLoginCluster::Login(Callback::Cancelable * onSuccessCallback, VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // tempAccountIdentifier: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), tempAccountIdentifier)); + SuccessOrExit(err = writer->PutString( + TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(tempAccountIdentifier.data()), tempAccountIdentifier.size()))); // setupPIN: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), setupPIN)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(setupPIN.data()), setupPIN.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -457,11 +463,13 @@ CHIP_ERROR ApplicationLauncherCluster::LaunchApp(Callback::Cancelable * onSucces VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // data: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), data)); + SuccessOrExit( + err = writer->PutString(TLV::ContextTag(argSeqNumber++), Span(Uint8::to_const_char(data.data()), data.size()))); // catalogVendorId: int16u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), catalogVendorId)); // applicationId: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), applicationId)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(applicationId.data()), applicationId.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -554,7 +562,8 @@ CHIP_ERROR AudioOutputCluster::RenameOutput(Callback::Cancelable * onSuccessCall // index: int8u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), index)); // name: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), name)); + SuccessOrExit( + err = writer->PutString(TLV::ContextTag(argSeqNumber++), Span(Uint8::to_const_char(name.data()), name.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -3451,7 +3460,8 @@ CHIP_ERROR ContentLauncherCluster::LaunchContent(Callback::Cancelable * onSucces // autoPlay: boolean SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), autoPlay)); // data: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), data)); + SuccessOrExit( + err = writer->PutString(TLV::ContextTag(argSeqNumber++), Span(Uint8::to_const_char(data.data()), data.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -3492,9 +3502,11 @@ CHIP_ERROR ContentLauncherCluster::LaunchURL(Callback::Cancelable * onSuccessCal VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // contentURL: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), contentURL)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(contentURL.data()), contentURL.size()))); // displayString: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), displayString)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(displayString.data()), displayString.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -5213,7 +5225,8 @@ CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable // location: regulatoryLocationType SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), location)); // countryCode: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), countryCode)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(countryCode.data()), countryCode.size()))); // breadcrumb: int64u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), breadcrumb)); // timeoutMs: int32u @@ -5427,7 +5440,8 @@ CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Cal // groupId: int16u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), groupId)); // groupName: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), groupName)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(groupName.data()), groupName.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -5470,7 +5484,8 @@ CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccess // groupId: int16u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), groupId)); // groupName: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), groupName)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(groupName.data()), groupName.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -6425,7 +6440,8 @@ CHIP_ERROR MediaInputCluster::RenameInput(Callback::Cancelable * onSuccessCallba // index: int8u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), index)); // name: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), name)); + SuccessOrExit( + err = writer->PutString(TLV::ContextTag(argSeqNumber++), Span(Uint8::to_const_char(name.data()), name.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -7672,7 +7688,8 @@ CHIP_ERROR OtaSoftwareUpdateProviderCluster::QueryImage(Callback::Cancelable * o // protocolsSupported: OTADownloadProtocol SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), protocolsSupported)); // location: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), location)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(location.data()), location.size()))); // requestorCanConsent: boolean SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), requestorCanConsent)); // metadataForProvider: octetString @@ -8657,7 +8674,8 @@ CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // label: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), label)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(label.data()), label.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -9202,7 +9220,8 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal // transitionTime: int16u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), transitionTime)); // sceneName: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), sceneName)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(sceneName.data()), sceneName.size()))); // clusterId: clusterId SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), clusterId)); // length: int8u @@ -9725,7 +9744,8 @@ CHIP_ERROR TvChannelCluster::ChangeChannel(Callback::Cancelable * onSuccessCallb VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // match: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), match)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(match.data()), match.size()))); SuccessOrExit(err = sender->FinishCommand()); @@ -9903,7 +9923,8 @@ CHIP_ERROR TargetNavigatorCluster::NavigateTarget(Callback::Cancelable * onSucce // target: int8u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), target)); // data: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), data)); + SuccessOrExit( + err = writer->PutString(TLV::ContextTag(argSeqNumber++), Span(Uint8::to_const_char(data.data()), data.size()))); SuccessOrExit(err = sender->FinishCommand()); diff --git a/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp index 51ab5b6323c824..6215a66e09446f 100644 --- a/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/controller-clusters/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -5260,8 +5261,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { default: @@ -5271,8 +5270,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp b/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp index c109f5d26e71e1..dd93297e0569bb 100644 --- a/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp index 175026107d05bb..8d6971d23c46d2 100644 --- a/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,1456 +121,221 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ColorLoopSet::Id: { Commands::ColorLoopSet::DecodableType commandData; - expectArgumentCount = 7; - uint8_t updateFlags; - uint8_t action; - uint8_t direction; - uint16_t time; - uint16_t startHue; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateFlags); - break; - case 1: - TLVUnpackError = aDataTlv.Get(action); - break; - case 2: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 3: - TLVUnpackError = aDataTlv.Get(time); - break; - case 4: - TLVUnpackError = aDataTlv.Get(startHue); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 6: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterColorLoopSetCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - updateFlags, action, direction, time, startHue, - optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterColorLoopSetCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateFlags, + to_underlying(commandData.action), to_underlying(commandData.direction), commandData.time, commandData.startHue, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::EnhancedMoveHue::Id: { Commands::EnhancedMoveHue::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint16_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfColorControlClusterEnhancedMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterEnhancedMoveHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::EnhancedMoveToHue::Id: { Commands::EnhancedMoveToHue::DecodableType commandData; - expectArgumentCount = 5; - uint16_t enhancedHue; - uint8_t direction; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(enhancedHue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterEnhancedMoveToHueCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, enhancedHue, direction, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.enhancedHue, + to_underlying(commandData.direction), commandData.transitionTime, commandData.optionsMask, + commandData.optionsOverride, commandData); } break; } case Commands::EnhancedMoveToHueAndSaturation::Id: { Commands::EnhancedMoveToHueAndSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint16_t enhancedHue; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(enhancedHue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterEnhancedMoveToHueAndSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, enhancedHue, saturation, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.enhancedHue, commandData.saturation, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::EnhancedStepHue::Id: { Commands::EnhancedStepHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint16_t stepSize; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterEnhancedStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterEnhancedStepHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveColor::Id: { Commands::MoveColor::DecodableType commandData; - expectArgumentCount = 4; - int16_t rateX; - int16_t rateY; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(rateX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rateY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterMoveColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - rateX, rateY, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rateX, commandData.rateY, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveColorTemperature::Id: { Commands::MoveColorTemperature::DecodableType commandData; - expectArgumentCount = 6; - uint8_t moveMode; - uint16_t rate; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, rate, colorTemperatureMinimum, - colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, commandData.optionsMask, + commandData.optionsOverride, commandData); } break; } case Commands::MoveHue::Id: { Commands::MoveHue::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveSaturation::Id: { Commands::MoveSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterMoveSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColor::Id: { Commands::MoveToColor::DecodableType commandData; - expectArgumentCount = 5; - uint16_t colorX; - uint16_t colorY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(colorY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveToColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - colorX, colorY, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveToColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorX, commandData.colorY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColorTemperature::Id: { Commands::MoveToColorTemperature::DecodableType commandData; - expectArgumentCount = 4; - uint16_t colorTemperature; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorTemperature); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, colorTemperature, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorTemperature, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHue::Id: { Commands::MoveToHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t direction; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterMoveToHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, - direction, transitionTime, optionsMask, optionsOverride, - commandData); + wasHandled = emberAfColorControlClusterMoveToHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, to_underlying(commandData.direction), + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHueAndSaturation::Id: { Commands::MoveToHueAndSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToHueAndSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, saturation, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, commandData.saturation, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToSaturation::Id: { Commands::MoveToSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, saturation, transitionTime, optionsMask, optionsOverride, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.saturation, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColor::Id: { Commands::StepColor::DecodableType commandData; - expectArgumentCount = 5; - int16_t stepX; - int16_t stepY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterStepColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepX, stepY, - transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.stepX, commandData.stepY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColorTemperature::Id: { Commands::StepColorTemperature::DecodableType commandData; - expectArgumentCount = 7; - uint8_t stepMode; - uint16_t stepSize; - uint16_t transitionTime; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 6: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStepColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, transitionTime, - colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepHue::Id: { Commands::StepHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, - stepSize, transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepSaturation::Id: { Commands::StepSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterStepSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StopMoveStep::Id: { Commands::StopMoveStep::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStopMoveStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionsMask, optionsOverride, commandData); + commandData.optionsMask, commandData.optionsOverride, + commandData); } break; } @@ -1708,18 +347,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1733,81 +365,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -1819,18 +389,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1844,20 +407,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetCounts::Id: { Commands::ResetCounts::DecodableType commandData; - - wasHandled = emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -1868,18 +430,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1893,161 +448,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -2059,18 +494,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -2084,502 +512,96 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Move::Id: { Commands::Move::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevel::Id: { Commands::MoveToLevel::DecodableType commandData; - expectArgumentCount = 4; - uint8_t level; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.level, commandData.transitionTime, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevelWithOnOff::Id: { Commands::MoveToLevelWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t level; - uint16_t transitionTime; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.level, + commandData.transitionTime, commandData); } break; } case Commands::MoveWithOnOff::Id: { Commands::MoveWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t moveMode; - uint8_t rate; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, commandData); + to_underlying(commandData.moveMode), commandData.rate, + commandData); } break; } case Commands::Step::Id: { Commands::Step::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterStepCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StepWithOnOff::Id: { Commands::StepWithOnOff::DecodableType commandData; - expectArgumentCount = 3; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData); } break; } case Commands::Stop::Id: { Commands::Stop::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionMask, optionOverride, commandData); + wasHandled = + emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StopWithOnOff::Id: { Commands::StopWithOnOff::DecodableType commandData; - - wasHandled = - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -2590,18 +612,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -2615,624 +630,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -3244,18 +741,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3269,31 +759,36 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Off::Id: { Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::On::Id: { Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::Toggle::Id: { Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -3304,18 +799,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3329,574 +817,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -3908,18 +922,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3933,20 +940,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetWatermarks::Id: { Commands::ResetWatermarks::DecodableType commandData; - - wasHandled = emberAfSoftwareDiagnosticsClusterResetWatermarksCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfSoftwareDiagnosticsClusterResetWatermarksCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -3957,18 +963,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3982,20 +981,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetCounts::Id: { Commands::ResetCounts::DecodableType commandData; - - wasHandled = emberAfThreadNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfThreadNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -4006,18 +1004,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4031,20 +1022,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ResetCounts::Id: { Commands::ResetCounts::DecodableType commandData; - - wasHandled = emberAfWiFiNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfWiFiNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -4055,18 +1045,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4081,8 +1064,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -4128,8 +1109,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp index bb94b39f82829b..17aa3a14ecded4 100644 --- a/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/lock-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,81 +121,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -333,18 +145,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -358,161 +163,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -524,18 +209,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -549,624 +227,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -1178,18 +338,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1203,31 +356,36 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Off::Id: { Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::On::Id: { Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::Toggle::Id: { Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -1238,18 +396,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1263,574 +414,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -1842,18 +519,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1868,8 +538,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -1897,8 +565,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/ota-provider-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/ota-provider-app/zap-generated/IMClusterCommandHandler.cpp index db872ce489523d..d9eb2de44e2d51 100644 --- a/zzz_generated/ota-provider-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/ota-provider-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,230 +58,43 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ApplyUpdateRequest::Id: { Commands::ApplyUpdateRequest::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t newVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(newVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, newVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.newVersion, + commandData); } break; } case Commands::NotifyUpdateApplied::Id: { Commands::NotifyUpdateApplied::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t softwareVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, softwareVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.softwareVersion, + commandData); } break; } case Commands::QueryImage::Id: { Commands::QueryImage::DecodableType commandData; - expectArgumentCount = 8; - uint16_t vendorId; - uint16_t productId; - uint16_t hardwareVersion; - uint32_t softwareVersion; - uint8_t protocolsSupported; - const uint8_t * location; - bool requestorCanConsent; - chip::ByteSpan metadataForProvider; - bool argExists[8]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 8) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(vendorId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(productId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(hardwareVersion); - break; - case 3: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - case 4: - TLVUnpackError = aDataTlv.Get(protocolsSupported); - break; - case 5: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(location); - break; - case 6: - TLVUnpackError = aDataTlv.Get(requestorCanConsent); - break; - case 7: - TLVUnpackError = aDataTlv.Get(metadataForProvider); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, vendorId, productId, hardwareVersion, softwareVersion, - protocolsSupported, const_cast(location), requestorCanConsent, metadataForProvider, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.vendorId, commandData.productId, + commandData.hardwareVersion, commandData.softwareVersion, to_underlying(commandData.protocolsSupported), + const_cast(Uint8::from_const_char(commandData.location.data())), commandData.requestorCanConsent, + commandData.metadataForProvider, commandData); } break; } @@ -292,18 +106,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -317,450 +124,80 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } @@ -772,18 +209,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -798,8 +228,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::OtaSoftwareUpdateProvider::Id: @@ -815,8 +243,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/ota-requestor-app/zap-generated/CHIPClusters.cpp b/zzz_generated/ota-requestor-app/zap-generated/CHIPClusters.cpp index e07c04c71151f7..83b3be7825ffa7 100644 --- a/zzz_generated/ota-requestor-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/ota-requestor-app/zap-generated/CHIPClusters.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -172,7 +173,8 @@ CHIP_ERROR OtaSoftwareUpdateProviderCluster::QueryImage(Callback::Cancelable * o // protocolsSupported: OTADownloadProtocol SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), protocolsSupported)); // location: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), location)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(location.data()), location.size()))); // requestorCanConsent: boolean SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), requestorCanConsent)); // metadataForProvider: octetString diff --git a/zzz_generated/ota-requestor-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/ota-requestor-app/zap-generated/IMClusterCommandHandler.cpp index 39617b59de12d4..d99383eabcae0b 100644 --- a/zzz_generated/ota-requestor-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/ota-requestor-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -254,8 +255,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { default: @@ -265,8 +264,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp b/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp index fbb9e867bd7d41..b051f7624f96f3 100644 --- a/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/zzz_generated/pump-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/pump-app/zap-generated/IMClusterCommandHandler.cpp index 4e9b89742b34cb..39db8e6d466b3d 100644 --- a/zzz_generated/pump-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/pump-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -256,81 +130,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -342,18 +154,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -367,161 +172,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -533,18 +218,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -558,502 +236,96 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Move::Id: { Commands::Move::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevel::Id: { Commands::MoveToLevel::DecodableType commandData; - expectArgumentCount = 4; - uint8_t level; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.level, commandData.transitionTime, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevelWithOnOff::Id: { Commands::MoveToLevelWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t level; - uint16_t transitionTime; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.level, + commandData.transitionTime, commandData); } break; } case Commands::MoveWithOnOff::Id: { Commands::MoveWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t moveMode; - uint8_t rate; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, commandData); + to_underlying(commandData.moveMode), commandData.rate, + commandData); } break; } case Commands::Step::Id: { Commands::Step::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterStepCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StepWithOnOff::Id: { Commands::StepWithOnOff::DecodableType commandData; - expectArgumentCount = 3; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData); } break; } case Commands::Stop::Id: { Commands::Stop::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionMask, optionOverride, commandData); + wasHandled = + emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StopWithOnOff::Id: { Commands::StopWithOnOff::DecodableType commandData; - - wasHandled = - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -1064,18 +336,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1089,564 +354,96 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -1658,18 +455,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1683,31 +473,36 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Off::Id: { Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::On::Id: { Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::Toggle::Id: { Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -1718,18 +513,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1743,574 +531,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -2322,18 +636,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -2348,8 +655,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -2383,8 +688,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp b/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp index c07cd9f4761704..23c932b1fd15ca 100644 --- a/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/zzz_generated/pump-controller-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/pump-controller-app/zap-generated/IMClusterCommandHandler.cpp index b730298ab4ff01..1e288cf290cbe0 100644 --- a/zzz_generated/pump-controller-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/pump-controller-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -256,81 +130,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -342,18 +154,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -367,161 +172,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -533,18 +218,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -558,624 +236,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -1187,18 +347,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1212,574 +365,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -1791,18 +470,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1817,8 +489,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -1846,8 +516,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/temperature-measurement-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/temperature-measurement-app/zap-generated/IMClusterCommandHandler.cpp index c0be9a7cb549ea..8a4bfad97b2284 100644 --- a/zzz_generated/temperature-measurement-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/temperature-measurement-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,81 +121,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -333,18 +145,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -358,161 +163,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -524,18 +209,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -549,488 +227,84 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -1042,18 +316,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1067,574 +334,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -1646,18 +439,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1672,8 +458,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -1698,8 +482,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/thermostat/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/thermostat/zap-generated/IMClusterCommandHandler.cpp index 0850b67ef1ce30..1a29f7052d12ed 100644 --- a/zzz_generated/thermostat/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/thermostat/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,80 +121,29 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::BarrierControlGoToPercent::Id: { Commands::BarrierControlGoToPercent::DecodableType commandData; - expectArgumentCount = 1; - uint8_t percentOpen; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(percentOpen); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfBarrierControlClusterBarrierControlGoToPercentCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, percentOpen, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.percentOpen, commandData); } break; } case Commands::BarrierControlStop::Id: { Commands::BarrierControlStop::DecodableType commandData; - - wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -331,18 +154,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -365,156 +181,30 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Bind::Id: { Commands::Bind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(nodeId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); } break; } case Commands::Unbind::Id: { Commands::Unbind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(nodeId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); } break; } @@ -526,18 +216,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -551,1067 +234,164 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::MoveColor::Id: { Commands::MoveColor::DecodableType commandData; - expectArgumentCount = 4; - int16_t rateX; - int16_t rateY; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(rateX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rateY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - rateX, rateY, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rateX, commandData.rateY, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveColorTemperature::Id: { Commands::MoveColorTemperature::DecodableType commandData; - expectArgumentCount = 6; - uint8_t moveMode; - uint16_t rate; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, rate, colorTemperatureMinimum, - colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, commandData.optionsMask, + commandData.optionsOverride, commandData); } break; } case Commands::MoveHue::Id: { Commands::MoveHue::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveSaturation::Id: { Commands::MoveSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfColorControlClusterMoveSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColor::Id: { Commands::MoveToColor::DecodableType commandData; - expectArgumentCount = 5; - uint16_t colorX; - uint16_t colorY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(colorY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterMoveToColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - colorX, colorY, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveToColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorX, commandData.colorY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColorTemperature::Id: { Commands::MoveToColorTemperature::DecodableType commandData; - expectArgumentCount = 4; - uint16_t colorTemperature; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorTemperature); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, colorTemperature, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorTemperature, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHue::Id: { Commands::MoveToHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t direction; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveToHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, - direction, transitionTime, optionsMask, optionsOverride, - commandData); + wasHandled = emberAfColorControlClusterMoveToHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, to_underlying(commandData.direction), + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHueAndSaturation::Id: { Commands::MoveToHueAndSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToHueAndSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, saturation, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, commandData.saturation, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToSaturation::Id: { Commands::MoveToSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, saturation, transitionTime, optionsMask, optionsOverride, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.saturation, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColor::Id: { Commands::StepColor::DecodableType commandData; - expectArgumentCount = 5; - int16_t stepX; - int16_t stepY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterStepColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepX, stepY, - transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.stepX, commandData.stepY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColorTemperature::Id: { Commands::StepColorTemperature::DecodableType commandData; - expectArgumentCount = 7; - uint8_t stepMode; - uint16_t stepSize; - uint16_t transitionTime; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 6: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStepColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, transitionTime, - colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepHue::Id: { Commands::StepHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, - stepSize, transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepSaturation::Id: { Commands::StepSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterStepSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StopMoveStep::Id: { Commands::StopMoveStep::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStopMoveStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionsMask, optionsOverride, commandData); + commandData.optionsMask, commandData.optionsOverride, + commandData); } break; } @@ -1623,18 +403,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1648,81 +421,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -1734,18 +445,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1759,1385 +463,246 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ClearAllPins::Id: { Commands::ClearAllPins::DecodableType commandData; - - wasHandled = - emberAfDoorLockClusterClearAllPinsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfDoorLockClusterClearAllPinsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::ClearAllRfids::Id: { Commands::ClearAllRfids::DecodableType commandData; - - wasHandled = - emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::ClearHolidaySchedule::Id: { Commands::ClearHolidaySchedule::DecodableType commandData; - expectArgumentCount = 1; - uint8_t scheduleId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterClearHolidayScheduleCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, scheduleId, commandData); + wasHandled = emberAfDoorLockClusterClearHolidayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData); } break; } case Commands::ClearPin::Id: { Commands::ClearPin::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::ClearRfid::Id: { Commands::ClearRfid::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::ClearWeekdaySchedule::Id: { Commands::ClearWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterClearWeekdayScheduleCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, userId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::ClearYeardaySchedule::Id: { Commands::ClearYeardaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterClearYeardayScheduleCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, userId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::GetHolidaySchedule::Id: { Commands::GetHolidaySchedule::DecodableType commandData; - expectArgumentCount = 1; - uint8_t scheduleId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterGetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, commandData); + commandData.scheduleId, commandData); } break; } case Commands::GetLogRecord::Id: { Commands::GetLogRecord::DecodableType commandData; - expectArgumentCount = 1; - uint16_t logIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(logIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterGetLogRecordCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - logIndex, commandData); + commandData.logIndex, commandData); } break; } case Commands::GetPin::Id: { Commands::GetPin::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = - emberAfDoorLockClusterGetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, commandData); + wasHandled = emberAfDoorLockClusterGetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetRfid::Id: { Commands::GetRfid::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetUserType::Id: { Commands::GetUserType::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetWeekdaySchedule::Id: { Commands::GetWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfDoorLockClusterGetWeekdayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterGetWeekdayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, commandData); - } - break; - } - case Commands::GetYeardaySchedule::Id: { - Commands::GetYeardaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + break; + } + case Commands::GetYeardaySchedule::Id: { + Commands::GetYeardaySchedule::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterGetYeardayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, commandData); + wasHandled = emberAfDoorLockClusterGetYeardayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::LockDoor::Id: { Commands::LockDoor::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan PIN; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(PIN); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfDoorLockClusterLockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, PIN, commandData); + wasHandled = emberAfDoorLockClusterLockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.pin, commandData); } break; } case Commands::SetHolidaySchedule::Id: { Commands::SetHolidaySchedule::DecodableType commandData; - expectArgumentCount = 4; - uint8_t scheduleId; - uint32_t localStartTime; - uint32_t localEndTime; - uint8_t operatingModeDuringHoliday; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(localStartTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(localEndTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, localStartTime, localEndTime, - operatingModeDuringHoliday, commandData); + wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.localStartTime, + commandData.localEndTime, commandData.operatingModeDuringHoliday, commandData); } break; } case Commands::SetPin::Id: { Commands::SetPin::DecodableType commandData; - expectArgumentCount = 4; - uint16_t userId; - uint8_t userStatus; - uint8_t userType; - chip::ByteSpan pin; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userStatus); - break; - case 2: - TLVUnpackError = aDataTlv.Get(userType); - break; - case 3: - TLVUnpackError = aDataTlv.Get(pin); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterSetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userStatus, userType, pin, commandData); + wasHandled = emberAfDoorLockClusterSetPinCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.userId, to_underlying(commandData.userStatus), + to_underlying(commandData.userType), commandData.pin, commandData); } break; } case Commands::SetRfid::Id: { Commands::SetRfid::DecodableType commandData; - expectArgumentCount = 4; - uint16_t userId; - uint8_t userStatus; - uint8_t userType; - chip::ByteSpan id; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userStatus); - break; - case 2: - TLVUnpackError = aDataTlv.Get(userType); - break; - case 3: - TLVUnpackError = aDataTlv.Get(id); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterSetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userStatus, userType, id, commandData); + wasHandled = emberAfDoorLockClusterSetRfidCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.userId, to_underlying(commandData.userStatus), + to_underlying(commandData.userType), commandData.id, commandData); } break; } case Commands::SetUserType::Id: { Commands::SetUserType::DecodableType commandData; - expectArgumentCount = 2; - uint16_t userId; - uint8_t userType; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userType, commandData); + wasHandled = + emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, to_underlying(commandData.userType), commandData); } break; } case Commands::SetWeekdaySchedule::Id: { Commands::SetWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 7; - uint8_t scheduleId; - uint16_t userId; - uint8_t daysMask; - uint8_t startHour; - uint8_t startMinute; - uint8_t endHour; - uint8_t endMinute; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(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: - TLVUnpackError = aDataTlv.Get(startMinute); - break; - case 5: - TLVUnpackError = aDataTlv.Get(endHour); - break; - case 6: - TLVUnpackError = aDataTlv.Get(endMinute); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, daysMask, startHour, startMinute, - endHour, endMinute, commandData); + wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, + commandData.daysMask, commandData.startHour, commandData.startMinute, commandData.endHour, + commandData.endMinute, commandData); } break; } case Commands::SetYeardaySchedule::Id: { Commands::SetYeardaySchedule::DecodableType commandData; - expectArgumentCount = 4; - uint8_t scheduleId; - uint16_t userId; - uint32_t localStartTime; - uint32_t localEndTime; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(localStartTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(localEndTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfDoorLockClusterSetYeardayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, localStartTime, localEndTime, commandData); + wasHandled = emberAfDoorLockClusterSetYeardayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, + commandData.localStartTime, commandData.localEndTime, commandData); } break; } case Commands::UnlockDoor::Id: { Commands::UnlockDoor::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan PIN; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(PIN); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, PIN, - commandData); + wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.pin, commandData); } break; } case Commands::UnlockWithTimeout::Id: { Commands::UnlockWithTimeout::DecodableType commandData; - expectArgumentCount = 2; - uint16_t timeoutInSeconds; - chip::ByteSpan pin; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutInSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(pin); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - timeoutInSeconds, pin, commandData); + wasHandled = + emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.timeoutInSeconds, commandData.pin, commandData); } break; } @@ -3149,18 +714,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3174,161 +732,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -3340,18 +778,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3365,334 +796,70 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddGroup::Id: { Commands::AddGroup::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - const uint8_t * groupName; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(groupName); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - const_cast(groupName), commandData); + wasHandled = emberAfGroupsClusterAddGroupCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, + const_cast(Uint8::from_const_char(commandData.groupName.data())), commandData); } break; } case Commands::AddGroupIfIdentifying::Id: { Commands::AddGroupIfIdentifying::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - const uint8_t * groupName; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(groupName); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGroupsClusterAddGroupIfIdentifyingCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, const_cast(groupName), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, + const_cast(Uint8::from_const_char(commandData.groupName.data())), commandData); } break; } case Commands::GetGroupMembership::Id: { Commands::GetGroupMembership::DecodableType commandData; - expectArgumentCount = 2; - uint8_t groupCount; - /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupCount); - break; - case 1: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupCount, groupList, commandData); + commandData.groupCount, nullptr, commandData); } break; } case Commands::RemoveAllGroups::Id: { Commands::RemoveAllGroups::DecodableType commandData; - - wasHandled = - emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::RemoveGroup::Id: { Commands::RemoveGroup::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - commandData); + wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData); } break; } case Commands::ViewGroup::Id: { Commands::ViewGroup::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - commandData); + wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData); } break; } @@ -3704,18 +871,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3729,76 +889,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ZoneEnrollResponse::Id: { Commands::ZoneEnrollResponse::DecodableType commandData; - expectArgumentCount = 2; - uint8_t enrollResponseCode; - uint8_t zoneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(enrollResponseCode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(zoneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfIasZoneClusterZoneEnrollResponseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - enrollResponseCode, zoneId, commandData); + to_underlying(commandData.enrollResponseCode), + commandData.zoneId, commandData); } break; } @@ -3810,18 +913,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3835,80 +931,29 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Identify::Id: { Commands::Identify::DecodableType commandData; - expectArgumentCount = 1; - uint16_t identifyTime; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(identifyTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - identifyTime, commandData); + commandData.identifyTime, commandData); } break; } case Commands::IdentifyQuery::Id: { Commands::IdentifyQuery::DecodableType commandData; - - wasHandled = - emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -3919,18 +964,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3944,502 +982,96 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Move::Id: { Commands::Move::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevel::Id: { Commands::MoveToLevel::DecodableType commandData; - expectArgumentCount = 4; - uint8_t level; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.level, commandData.transitionTime, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevelWithOnOff::Id: { Commands::MoveToLevelWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t level; - uint16_t transitionTime; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.level, + commandData.transitionTime, commandData); } break; } case Commands::MoveWithOnOff::Id: { Commands::MoveWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t moveMode; - uint8_t rate; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, commandData); + to_underlying(commandData.moveMode), commandData.rate, + commandData); } break; } case Commands::Step::Id: { Commands::Step::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterStepCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StepWithOnOff::Id: { Commands::StepWithOnOff::DecodableType commandData; - expectArgumentCount = 3; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData); } break; } case Commands::Stop::Id: { Commands::Stop::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionMask, optionOverride, commandData); + wasHandled = + emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StopWithOnOff::Id: { Commands::StopWithOnOff::DecodableType commandData; - - wasHandled = - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -4450,18 +1082,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4475,19 +1100,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Sleep::Id: { Commands::Sleep::DecodableType commandData; - - wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -4498,18 +1122,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4523,624 +1140,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { - Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + Commands::DisableNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -5152,18 +1251,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5177,230 +1269,43 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ApplyUpdateRequest::Id: { Commands::ApplyUpdateRequest::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t newVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(newVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, newVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.newVersion, + commandData); } break; } case Commands::NotifyUpdateApplied::Id: { Commands::NotifyUpdateApplied::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t softwareVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, softwareVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.softwareVersion, + commandData); } break; } case Commands::QueryImage::Id: { Commands::QueryImage::DecodableType commandData; - expectArgumentCount = 8; - uint16_t vendorId; - uint16_t productId; - uint16_t hardwareVersion; - uint32_t softwareVersion; - uint8_t protocolsSupported; - const uint8_t * location; - bool requestorCanConsent; - chip::ByteSpan metadataForProvider; - bool argExists[8]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 8) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(vendorId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(productId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(hardwareVersion); - break; - case 3: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - case 4: - TLVUnpackError = aDataTlv.Get(protocolsSupported); - break; - case 5: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(location); - break; - case 6: - TLVUnpackError = aDataTlv.Get(requestorCanConsent); - break; - case 7: - TLVUnpackError = aDataTlv.Get(metadataForProvider); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, vendorId, productId, hardwareVersion, softwareVersion, - protocolsSupported, const_cast(location), requestorCanConsent, metadataForProvider, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.vendorId, commandData.productId, + commandData.hardwareVersion, commandData.softwareVersion, to_underlying(commandData.protocolsSupported), + const_cast(Uint8::from_const_char(commandData.location.data())), commandData.requestorCanConsent, + commandData.metadataForProvider, commandData); } break; } @@ -5412,18 +1317,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5437,31 +1335,36 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Off::Id: { Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::On::Id: { Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::Toggle::Id: { Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -5472,18 +1375,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5497,574 +1393,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -6076,18 +1498,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6101,471 +1516,81 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddScene::Id: { Commands::AddScene::DecodableType commandData; - expectArgumentCount = 5; - uint16_t groupId; - uint8_t sceneId; - uint16_t transitionTime; - const uint8_t * sceneName; - /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - break; - case 4: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterAddSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, transitionTime, const_cast(sceneName), - extensionFieldSets, commandData); + wasHandled = emberAfScenesClusterAddSceneCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, commandData.sceneId, + commandData.transitionTime, const_cast(Uint8::from_const_char(commandData.sceneName.data())), + nullptr, commandData); } break; } case Commands::GetSceneMembership::Id: { Commands::GetSceneMembership::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupId, commandData); + commandData.groupId, commandData); } break; } case Commands::RecallScene::Id: { Commands::RecallScene::DecodableType commandData; - expectArgumentCount = 3; - uint16_t groupId; - uint8_t sceneId; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, transitionTime, commandData); + wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, + commandData.transitionTime, commandData); } break; } case Commands::RemoveAllScenes::Id: { Commands::RemoveAllScenes::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupId, commandData); + commandData.groupId, commandData); } break; } case Commands::RemoveScene::Id: { Commands::RemoveScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } case Commands::StoreScene::Id: { Commands::StoreScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } case Commands::ViewScene::Id: { Commands::ViewScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } @@ -6577,18 +1602,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6602,33 +1620,39 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Test::Id: { Commands::Test::DecodableType commandData; - - wasHandled = emberAfTestClusterClusterTestCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfTestClusterClusterTestCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::TestNotHandled::Id: { Commands::TestNotHandled::DecodableType commandData; - - wasHandled = - emberAfTestClusterClusterTestNotHandledCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfTestClusterClusterTestNotHandledCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } case Commands::TestSpecific::Id: { Commands::TestSpecific::DecodableType commandData; - - wasHandled = - emberAfTestClusterClusterTestSpecificCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfTestClusterClusterTestSpecificCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -6639,18 +1663,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6664,221 +1681,51 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ClearWeeklySchedule::Id: { Commands::ClearWeeklySchedule::DecodableType commandData; - - wasHandled = emberAfThermostatClusterClearWeeklyScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfThermostatClusterClearWeeklyScheduleCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::GetWeeklySchedule::Id: { Commands::GetWeeklySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t daysToReturn; - uint8_t modeToReturn; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(daysToReturn); - break; - case 1: - TLVUnpackError = aDataTlv.Get(modeToReturn); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfThermostatClusterGetWeeklyScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - daysToReturn, modeToReturn, commandData); + commandData.daysToReturn, commandData.modeToReturn, + commandData); } break; } case Commands::SetWeeklySchedule::Id: { Commands::SetWeeklySchedule::DecodableType commandData; - expectArgumentCount = 4; - uint8_t numberOfTransitionsForSequence; - uint8_t dayOfWeekForSequence; - uint8_t modeForSequence; - /* TYPE WARNING: array array defaults to */ uint8_t * payload; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(numberOfTransitionsForSequence); - break; - case 1: - TLVUnpackError = aDataTlv.Get(dayOfWeekForSequence); - break; - case 2: - TLVUnpackError = aDataTlv.Get(modeForSequence); - break; - case 3: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(payload)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfThermostatClusterSetWeeklyScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - numberOfTransitionsForSequence, dayOfWeekForSequence, - modeForSequence, payload, commandData); + wasHandled = emberAfThermostatClusterSetWeeklyScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.numberOfTransitionsForSequence, + commandData.dayOfWeekForSequence, commandData.modeForSequence, nullptr, commandData); } break; } case Commands::SetpointRaiseLower::Id: { Commands::SetpointRaiseLower::DecodableType commandData; - expectArgumentCount = 2; - uint8_t mode; - int8_t amount; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(mode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(amount); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfThermostatClusterSetpointRaiseLowerCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, mode, amount, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.mode), commandData.amount, + commandData); } break; } @@ -6890,18 +1737,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6916,8 +1756,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -6987,8 +1825,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp b/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp index 261ba14e8af293..bcd6c22ab31055 100644 --- a/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -158,7 +159,8 @@ CHIP_ERROR GeneralCommissioningCluster::SetRegulatoryConfig(Callback::Cancelable // location: regulatoryLocationType SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), location)); // countryCode: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), countryCode)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(countryCode.data()), countryCode.size()))); // breadcrumb: int64u SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), breadcrumb)); // timeoutMs: int32u @@ -763,7 +765,8 @@ CHIP_ERROR OperationalCredentialsCluster::UpdateFabricLabel(Callback::Cancelable VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // label: charString - SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), label)); + SuccessOrExit(err = writer->PutString(TLV::ContextTag(argSeqNumber++), + Span(Uint8::to_const_char(label.data()), label.size()))); SuccessOrExit(err = sender->FinishCommand()); diff --git a/zzz_generated/tv-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/tv-app/zap-generated/IMClusterCommandHandler.cpp index b6a2c5a4f3110d..bddbfb284ec613 100644 --- a/zzz_generated/tv-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/tv-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,141 +58,31 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::GetSetupPIN::Id: { Commands::GetSetupPIN::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * tempAccountIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(tempAccountIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfAccountLoginClusterGetSetupPINCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - const_cast(tempAccountIdentifier), commandData); + wasHandled = emberAfAccountLoginClusterGetSetupPINCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.tempAccountIdentifier.data())), commandData); } break; } case Commands::Login::Id: { Commands::Login::DecodableType commandData; - expectArgumentCount = 2; - const uint8_t * tempAccountIdentifier; - const uint8_t * setupPIN; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(tempAccountIdentifier); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(setupPIN); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfAccountLoginClusterLoginCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - const_cast(tempAccountIdentifier), - const_cast(setupPIN), commandData); + wasHandled = emberAfAccountLoginClusterLoginCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.tempAccountIdentifier.data())), + const_cast(Uint8::from_const_char(commandData.setupPIN.data())), commandData); } break; } @@ -203,18 +94,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -228,161 +112,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -393,18 +157,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -418,72 +175,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ChangeStatus::Id: { Commands::ChangeStatus::DecodableType commandData; - expectArgumentCount = 1; - uint8_t status; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(status); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfApplicationBasicClusterChangeStatusCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, status, commandData); + wasHandled = emberAfApplicationBasicClusterChangeStatusCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.status), commandData); } break; } @@ -495,18 +198,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -520,83 +216,20 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::LaunchApp::Id: { Commands::LaunchApp::DecodableType commandData; - expectArgumentCount = 3; - const uint8_t * data; - uint16_t catalogVendorId; - const uint8_t * applicationId; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); - break; - case 1: - TLVUnpackError = aDataTlv.Get(catalogVendorId); - break; - case 2: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(applicationId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfApplicationLauncherClusterLaunchAppCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(data), catalogVendorId, - const_cast(applicationId), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.data.data())), commandData.catalogVendorId, + const_cast(Uint8::from_const_char(commandData.applicationId.data())), commandData); } break; } @@ -608,18 +241,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -633,137 +259,29 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RenameOutput::Id: { Commands::RenameOutput::DecodableType commandData; - expectArgumentCount = 2; - uint8_t index; - const uint8_t * name; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(index); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(name); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfAudioOutputClusterRenameOutputCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - index, const_cast(name), commandData); + wasHandled = emberAfAudioOutputClusterRenameOutputCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.index, + const_cast(Uint8::from_const_char(commandData.name.data())), commandData); } break; } case Commands::SelectOutput::Id: { Commands::SelectOutput::DecodableType commandData; - expectArgumentCount = 1; - uint8_t index; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(index); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAudioOutputClusterSelectOutputCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - index, commandData); + commandData.index, commandData); } break; } @@ -775,18 +293,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -809,95 +320,169 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Bind::Id: { Commands::Bind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(nodeId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); + } + break; + } + case Commands::Unbind::Id: { + Commands::Unbind::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } - if (CHIP_END_OF_TLV == TLVError) + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace Binding + +namespace ContentLauncher { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::LaunchContent::Id: { + Commands::LaunchContent::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfContentLauncherClusterLaunchContentCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.autoPlay, + const_cast(Uint8::from_const_char(commandData.data.data())), commandData); + } + break; + } + case Commands::LaunchURL::Id: { + Commands::LaunchURL::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfContentLauncherClusterLaunchURLCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.contentURL.data())), + const_cast(Uint8::from_const_char(commandData.displayString.data())), commandData); } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace ContentLauncher + +namespace DiagnosticLogs { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::RetrieveLogsRequest::Id: { + Commands::RetrieveLogsRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } - case Commands::Unbind::Id: { - Commands::Unbind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace DiagnosticLogs + +namespace GeneralCommissioning { + +void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::ArmFailSafeResponse::Id: { + expectArgumentCount = 2; + uint8_t errorCode; + const uint8_t * debugText; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -910,7 +495,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -927,16 +512,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(nodeId); + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -955,60 +535,17 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace Binding - -namespace ContentLauncher { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::LaunchContent::Id: { - Commands::LaunchContent::DecodableType commandData; + case Commands::CommissioningCompleteResponse::Id: { expectArgumentCount = 2; - bool autoPlay; - const uint8_t * data; + uint8_t errorCode; + const uint8_t * debugText; bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -1039,11 +576,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(autoPlay); + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -1064,16 +601,15 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfContentLauncherClusterLaunchContentCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, autoPlay, const_cast(data), commandData); + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - case Commands::LaunchURL::Id: { - Commands::LaunchURL::DecodableType commandData; + case Commands::SetRegulatoryConfigResponse::Id: { expectArgumentCount = 2; - const uint8_t * contentURL; - const uint8_t * displayString; + uint8_t errorCode; + const uint8_t * debugText; bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -1104,12 +640,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(contentURL); + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(displayString); + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -1130,9 +665,8 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfContentLauncherClusterLaunchURLCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - const_cast(contentURL), - const_cast(displayString), commandData); + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } @@ -1159,9 +693,9 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } -} // namespace ContentLauncher +} // namespace GeneralCommissioning -namespace DiagnosticLogs { +namespace GeneralCommissioning { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) { @@ -1169,81 +703,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { - case Commands::RetrieveLogsRequest::Id: { - Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::ArmFailSafe::Id: { + Commands::ArmFailSafe::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } - - if (CHIP_END_OF_TLV == TLVError) + break; + } + case Commands::CommissioningComplete::Id: { + Commands::CommissioningComplete::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + break; + } + case Commands::SetRegulatoryConfig::Id: { + Commands::SetRegulatoryConfig::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -1255,229 +749,154 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } -} // namespace DiagnosticLogs +} // namespace GeneralCommissioning -namespace GeneralCommissioning { +namespace KeypadInput { -void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) { // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. // Any error value TLVUnpackError means we have received an illegal value. // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { - case Commands::ArmFailSafeResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; + case Commands::SendKey::Id: { + Commands::SendKey::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfKeypadInputClusterSendKeyCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + to_underlying(commandData.keyCode), commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } - memset(argExists, 0, sizeof argExists); + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) +} // namespace KeypadInput + +namespace LevelControl { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::Move::Id: { + Commands::Move::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfLevelControlClusterMoveCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionMask, commandData.optionOverride, commandData); } - - if (CHIP_END_OF_TLV == TLVError) + break; + } + case Commands::MoveToLevel::Id: { + Commands::MoveToLevel::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfLevelControlClusterMoveToLevelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.level, commandData.transitionTime, + commandData.optionMask, commandData.optionOverride, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + break; + } + case Commands::MoveToLevelWithOnOff::Id: { + Commands::MoveToLevelWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.level, + commandData.transitionTime, commandData); } break; } - case Commands::CommissioningCompleteResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::MoveWithOnOff::Id: { + Commands::MoveWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + to_underlying(commandData.moveMode), commandData.rate, + commandData); } - - if (CHIP_END_OF_TLV == TLVError) + break; + } + case Commands::Step::Id: { + Commands::Step::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfLevelControlClusterStepCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionMask, commandData.optionOverride, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + break; + } + case Commands::StepWithOnOff::Id: { + Commands::StepWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData); } break; } - case Commands::SetRegulatoryConfigResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::Stop::Id: { + Commands::Stop::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = + emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.optionMask, commandData.optionOverride, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + break; + } + case Commands::StopWithOnOff::Id: { + Commands::StopWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); } break; } @@ -1489,24 +908,17 @@ void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPa } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } -} // namespace GeneralCommissioning +} // namespace LevelControl -namespace GeneralCommissioning { +namespace LowPower { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) { @@ -1514,161 +926,89 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { - case Commands::ArmFailSafe::Id: { - Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::Sleep::Id: { + Commands::Sleep::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) +} // namespace LowPower + +namespace MediaInput { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::HideInputStatus::Id: { + Commands::HideInputStatus::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + wasHandled = emberAfMediaInputClusterHideInputStatusCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); } break; } - case Commands::CommissioningComplete::Id: { - Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); - break; - } - case Commands::SetRegulatoryConfig::Id: { - Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::RenameInput::Id: { + Commands::RenameInput::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfMediaInputClusterRenameInputCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.index, + const_cast(Uint8::from_const_char(commandData.name.data())), commandData); } - - if (CHIP_END_OF_TLV == TLVError) + break; + } + case Commands::SelectInput::Id: { + Commands::SelectInput::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfMediaInputClusterSelectInputCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.index, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + break; + } + case Commands::ShowInputStatus::Id: { + Commands::ShowInputStatus::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + wasHandled = emberAfMediaInputClusterShowInputStatusCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); } break; } @@ -1680,24 +1020,17 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } -} // namespace GeneralCommissioning +} // namespace MediaInput -namespace KeypadInput { +namespace MediaPlayback { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) { @@ -1705,2943 +1038,118 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { - case Commands::SendKey::Id: { - Commands::SendKey::DecodableType commandData; - expectArgumentCount = 1; - uint8_t keyCode; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::MediaFastForward::Id: { + Commands::MediaFastForward::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(keyCode); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfKeypadInputClusterSendKeyCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, keyCode, - commandData); - } - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace KeypadInput - -namespace LevelControl { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::Move::Id: { - Commands::Move::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionMask, optionOverride, commandData); - } - break; - } - case Commands::MoveToLevel::Id: { - Commands::MoveToLevel::DecodableType commandData; - expectArgumentCount = 4; - uint8_t level; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, - transitionTime, optionMask, optionOverride, commandData); - } - break; - } - case Commands::MoveToLevelWithOnOff::Id: { - Commands::MoveToLevelWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t level; - uint16_t transitionTime; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, transitionTime, commandData); - } - break; - } - case Commands::MoveWithOnOff::Id: { - Commands::MoveWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t moveMode; - uint8_t rate; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, commandData); - } - break; - } - case Commands::Step::Id: { - Commands::Step::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, - transitionTime, optionMask, optionOverride, commandData); - } - break; - } - case Commands::StepWithOnOff::Id: { - Commands::StepWithOnOff::DecodableType commandData; - expectArgumentCount = 3; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, commandData); - } - break; - } - case Commands::Stop::Id: { - Commands::Stop::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionMask, optionOverride, commandData); - } - break; - } - case Commands::StopWithOnOff::Id: { - Commands::StopWithOnOff::DecodableType commandData; - - wasHandled = - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace LevelControl - -namespace LowPower { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::Sleep::Id: { - Commands::Sleep::DecodableType commandData; - - wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace LowPower - -namespace MediaInput { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::HideInputStatus::Id: { - Commands::HideInputStatus::DecodableType commandData; - - wasHandled = - emberAfMediaInputClusterHideInputStatusCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::RenameInput::Id: { - Commands::RenameInput::DecodableType commandData; - expectArgumentCount = 2; - uint8_t index; - const uint8_t * name; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(index); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(name); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfMediaInputClusterRenameInputCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - index, const_cast(name), commandData); - } - break; - } - case Commands::SelectInput::Id: { - Commands::SelectInput::DecodableType commandData; - expectArgumentCount = 1; - uint8_t index; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(index); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfMediaInputClusterSelectInputCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - index, commandData); - } - break; - } - case Commands::ShowInputStatus::Id: { - Commands::ShowInputStatus::DecodableType commandData; - - wasHandled = - emberAfMediaInputClusterShowInputStatusCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace MediaInput - -namespace MediaPlayback { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::MediaFastForward::Id: { - Commands::MediaFastForward::DecodableType commandData; - - wasHandled = emberAfMediaPlaybackClusterMediaFastForwardCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - commandData); - break; - } - case Commands::MediaNext::Id: { - Commands::MediaNext::DecodableType commandData; - - wasHandled = - emberAfMediaPlaybackClusterMediaNextCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::MediaPause::Id: { - Commands::MediaPause::DecodableType commandData; - - wasHandled = - emberAfMediaPlaybackClusterMediaPauseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::MediaPlay::Id: { - Commands::MediaPlay::DecodableType commandData; - - wasHandled = - emberAfMediaPlaybackClusterMediaPlayCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::MediaPrevious::Id: { - Commands::MediaPrevious::DecodableType commandData; - - wasHandled = - emberAfMediaPlaybackClusterMediaPreviousCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::MediaRewind::Id: { - Commands::MediaRewind::DecodableType commandData; - - wasHandled = - emberAfMediaPlaybackClusterMediaRewindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::MediaSeek::Id: { - Commands::MediaSeek::DecodableType commandData; - expectArgumentCount = 1; - uint64_t position; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(position); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfMediaPlaybackClusterMediaSeekCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - position, commandData); - } - break; - } - case Commands::MediaSkipBackward::Id: { - Commands::MediaSkipBackward::DecodableType commandData; - expectArgumentCount = 1; - uint64_t deltaPositionMilliseconds; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(deltaPositionMilliseconds); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, deltaPositionMilliseconds, commandData); - } - break; - } - case Commands::MediaSkipForward::Id: { - Commands::MediaSkipForward::DecodableType commandData; - expectArgumentCount = 1; - uint64_t deltaPositionMilliseconds; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(deltaPositionMilliseconds); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, deltaPositionMilliseconds, commandData); - } - break; - } - case Commands::MediaStartOver::Id: { - Commands::MediaStartOver::DecodableType commandData; - - wasHandled = emberAfMediaPlaybackClusterMediaStartOverCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - commandData); - break; - } - case Commands::MediaStop::Id: { - Commands::MediaStop::DecodableType commandData; - - wasHandled = - emberAfMediaPlaybackClusterMediaStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace MediaPlayback - -namespace NetworkCommissioning { - -void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::AddThreadNetworkResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); - } - break; - } - case Commands::AddWiFiNetworkResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); - } - break; - } - case Commands::DisableNetworkResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); - } - break; - } - case Commands::EnableNetworkResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); - } - break; - } - case Commands::RemoveNetworkResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); - } - break; - } - case Commands::ScanNetworksResponse::Id: { - expectArgumentCount = 4; - uint8_t errorCode; - const uint8_t * debugText; - /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; - /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - case 2: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(wifiScanResults)); - break; - case 3: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(threadScanResults)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText), wifiScanResults, - threadScanResults); - } - break; - } - case Commands::UpdateThreadNetworkResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); - } - break; - } - case Commands::UpdateWiFiNetworkResponse::Id: { - expectArgumentCount = 2; - uint8_t errorCode; - const uint8_t * debugText; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(errorCode); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(debugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback( - aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); - } - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace NetworkCommissioning - -namespace NetworkCommissioning { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::AddThreadNetwork::Id: { - Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); - } - break; - } - case Commands::AddWiFiNetwork::Id: { - Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); - } - break; - } - case Commands::DisableNetwork::Id: { - Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); - } - break; - } - case Commands::EnableNetwork::Id: { - Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); - } - break; - } - case Commands::GetLastNetworkCommissioningResult::Id: { - Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); - } - break; - } - case Commands::RemoveNetwork::Id: { - Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); - } - break; - } - case Commands::ScanNetworks::Id: { - Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); - } - break; - } - case Commands::UpdateThreadNetwork::Id: { - Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); - } - break; - } - case Commands::UpdateWiFiNetwork::Id: { - Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); - } - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace NetworkCommissioning - -namespace OtaSoftwareUpdateProvider { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::ApplyUpdateRequest::Id: { - Commands::ApplyUpdateRequest::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t newVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(newVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, newVersion, commandData); - } - break; - } - case Commands::NotifyUpdateApplied::Id: { - Commands::NotifyUpdateApplied::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t softwareVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, softwareVersion, commandData); - } - break; - } - case Commands::QueryImage::Id: { - Commands::QueryImage::DecodableType commandData; - expectArgumentCount = 8; - uint16_t vendorId; - uint16_t productId; - uint16_t hardwareVersion; - uint32_t softwareVersion; - uint8_t protocolsSupported; - const uint8_t * location; - bool requestorCanConsent; - chip::ByteSpan metadataForProvider; - bool argExists[8]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 8) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(vendorId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(productId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(hardwareVersion); - break; - case 3: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - case 4: - TLVUnpackError = aDataTlv.Get(protocolsSupported); - break; - case 5: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(location); - break; - case 6: - TLVUnpackError = aDataTlv.Get(requestorCanConsent); - break; - case 7: - TLVUnpackError = aDataTlv.Get(metadataForProvider); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) - { - wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, vendorId, productId, hardwareVersion, softwareVersion, - protocolsSupported, const_cast(location), requestorCanConsent, metadataForProvider, commandData); - } - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace OtaSoftwareUpdateProvider - -namespace OnOff { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::Off::Id: { - Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::On::Id: { - Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - case Commands::Toggle::Id: { - Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); - break; - } - default: { - // Unrecognized command ID, error status will apply. - ReportCommandUnsupported(apCommandObj, aCommandPath); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) - { - apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); - } -} - -} // namespace OnOff - -namespace OperationalCredentials { - -void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - // The following variables are used for all commands to save code size. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; - uint32_t validArgumentCount = 0; - uint32_t expectArgumentCount = 0; - uint32_t currentDecodeTagId = 0; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::AttestationResponse::Id: { - expectArgumentCount = 2; - chip::ByteSpan AttestationElements; - chip::ByteSpan Signature; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationElements); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Signature); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfOperationalCredentialsClusterAttestationResponseCallback(aCommandPath.mEndpointId, apCommandObj, - AttestationElements, Signature); + wasHandled = emberAfMediaPlaybackClusterMediaFastForwardCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); } break; } - case Commands::CertificateChainResponse::Id: { - expectArgumentCount = 1; - chip::ByteSpan Certificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(Certificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + case Commands::MediaNext::Id: { + Commands::MediaNext::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = + emberAfMediaPlaybackClusterMediaNextCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + break; + } + case Commands::MediaPause::Id: { + Commands::MediaPause::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfOperationalCredentialsClusterCertificateChainResponseCallback(aCommandPath.mEndpointId, - apCommandObj, Certificate); + wasHandled = emberAfMediaPlaybackClusterMediaPauseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); } break; } - case Commands::NOCResponse::Id: { - expectArgumentCount = 3; - uint8_t StatusCode; - uint8_t FabricIndex; - chip::ByteSpan DebugText; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::MediaPlay::Id: { + Commands::MediaPlay::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(StatusCode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - case 2: - TLVUnpackError = aDataTlv.Get(DebugText); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = + emberAfMediaPlaybackClusterMediaPlayCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); } - - if (CHIP_END_OF_TLV == TLVError) + break; + } + case Commands::MediaPrevious::Id: { + Commands::MediaPrevious::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfMediaPlaybackClusterMediaPreviousCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + break; + } + case Commands::MediaRewind::Id: { + Commands::MediaRewind::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfOperationalCredentialsClusterNOCResponseCallback(aCommandPath.mEndpointId, apCommandObj, - StatusCode, FabricIndex, DebugText); + wasHandled = emberAfMediaPlaybackClusterMediaRewindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); } break; } - case Commands::OpCSRResponse::Id: { - expectArgumentCount = 2; - chip::ByteSpan NOCSRElements; - chip::ByteSpan AttestationSignature; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + case Commands::MediaSeek::Id: { + Commands::MediaSeek::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCSRElements); - break; - case 1: - TLVUnpackError = aDataTlv.Get(AttestationSignature); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfMediaPlaybackClusterMediaSeekCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.position, commandData); } - - if (CHIP_END_OF_TLV == TLVError) + break; + } + case Commands::MediaSkipBackward::Id: { + Commands::MediaSkipBackward::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.deltaPositionMilliseconds, commandData); } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + break; + } + case Commands::MediaSkipForward::Id: { + Commands::MediaSkipForward::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfOperationalCredentialsClusterOpCSRResponseCallback(aCommandPath.mEndpointId, apCommandObj, - NOCSRElements, AttestationSignature); + wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.deltaPositionMilliseconds, commandData); + } + break; + } + case Commands::MediaStartOver::Id: { + Commands::MediaStartOver::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfMediaPlaybackClusterMediaStartOverCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } + break; + } + case Commands::MediaStop::Id: { + Commands::MediaStop::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfMediaPlaybackClusterMediaStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); } break; } @@ -4653,26 +1161,19 @@ void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPa } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } -} // namespace OperationalCredentials +} // namespace MediaPlayback -namespace OperationalCredentials { +namespace NetworkCommissioning { -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) { // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. @@ -4687,15 +1188,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP { switch (aCommandPath.mCommandId) { - case Commands::AddNOC::Id: { - Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; + case Commands::AddThreadNetworkResponse::Id: { + expectArgumentCount = 2; + uint8_t errorCode; + const uint8_t * debugText; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -4708,7 +1205,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -4725,19 +1222,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -4756,19 +1245,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - case Commands::AddTrustedRootCertificate::Id: { - Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; + case Commands::AddWiFiNetworkResponse::Id: { + expectArgumentCount = 2; + uint8_t errorCode; + const uint8_t * debugText; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -4781,7 +1269,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -4798,7 +1286,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); + TLVUnpackError = aDataTlv.Get(errorCode); + break; + case 1: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -4817,18 +1309,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - case Commands::AttestationRequest::Id: { - Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; + case Commands::DisableNetworkResponse::Id: { + expectArgumentCount = 2; + uint8_t errorCode; + const uint8_t * debugText; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -4841,7 +1333,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -4858,7 +1350,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); + TLVUnpackError = aDataTlv.Get(errorCode); + break; + case 1: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -4877,18 +1373,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - case Commands::CertificateChainRequest::Id: { - Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; + case Commands::EnableNetworkResponse::Id: { + expectArgumentCount = 2; + uint8_t errorCode; + const uint8_t * debugText; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -4901,7 +1397,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -4918,7 +1414,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); + TLVUnpackError = aDataTlv.Get(errorCode); + break; + case 1: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -4937,18 +1437,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - case Commands::OpCSRRequest::Id: { - Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; + case Commands::RemoveNetworkResponse::Id: { + expectArgumentCount = 2; + uint8_t errorCode; + const uint8_t * debugText; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -4961,7 +1461,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -4978,7 +1478,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); + TLVUnpackError = aDataTlv.Get(errorCode); + break; + case 1: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -4997,18 +1501,20 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - case Commands::RemoveFabric::Id: { - Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; + case Commands::ScanNetworksResponse::Id: { + expectArgumentCount = 4; + uint8_t errorCode; + const uint8_t * debugText; + /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; + /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; + bool argExists[4]; memset(argExists, 0, sizeof argExists); @@ -5021,7 +1527,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) + if (currentDecodeTagId < 4) { if (argExists[currentDecodeTagId]) { @@ -5038,67 +1544,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); + TLVUnpackError = aDataTlv.Get(errorCode); break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + case 1: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { + case 2: + // Just for compatibility, we will add array type support in IM later. + TLVUnpackError = aDataTlv.GetDataPtr(const_cast(wifiScanResults)); break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); - } - break; - } - case Commands::RemoveTrustedRootCertificate::Id: { - Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); + case 3: + // Just for compatibility, we will add array type support in IM later. + TLVUnpackError = aDataTlv.GetDataPtr(const_cast(threadScanResults)); break; default: // Unsupported tag, ignore it. @@ -5117,18 +1575,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText), wifiScanResults, + threadScanResults); } break; } - case Commands::UpdateFabricLabel::Id: { - Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; + case Commands::UpdateThreadNetworkResponse::Id: { + expectArgumentCount = 2; + uint8_t errorCode; + const uint8_t * debugText; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -5141,7 +1600,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -5158,8 +1617,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP 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(Label); + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -5178,18 +1640,17 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } - case Commands::UpdateNOC::Id: { - Commands::UpdateNOC::DecodableType commandData; + case Commands::UpdateWiFiNetworkResponse::Id: { expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; + uint8_t errorCode; + const uint8_t * debugText; bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -5220,10 +1681,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(debugText); break; default: // Unsupported tag, ignore it. @@ -5244,8 +1706,8 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback( + aCommandPath.mEndpointId, apCommandObj, errorCode, const_cast(debugText)); } break; } @@ -5272,11 +1734,264 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } -} // namespace OperationalCredentials +} // namespace NetworkCommissioning -namespace TvChannel { +namespace NetworkCommissioning { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::AddThreadNetwork::Id: { + Commands::AddThreadNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); + } + break; + } + case Commands::AddWiFiNetwork::Id: { + Commands::AddWiFiNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); + } + break; + } + case Commands::DisableNetwork::Id: { + Commands::DisableNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); + } + break; + } + case Commands::EnableNetwork::Id: { + Commands::EnableNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); + } + break; + } + case Commands::GetLastNetworkCommissioningResult::Id: { + Commands::GetLastNetworkCommissioningResult::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); + } + break; + } + case Commands::RemoveNetwork::Id: { + Commands::RemoveNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); + } + break; + } + case Commands::ScanNetworks::Id: { + Commands::ScanNetworks::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); + } + break; + } + case Commands::UpdateThreadNetwork::Id: { + Commands::UpdateThreadNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); + } + break; + } + case Commands::UpdateWiFiNetwork::Id: { + Commands::UpdateWiFiNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace NetworkCommissioning + +namespace OtaSoftwareUpdateProvider { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::ApplyUpdateRequest::Id: { + Commands::ApplyUpdateRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.newVersion, + commandData); + } + break; + } + case Commands::NotifyUpdateApplied::Id: { + Commands::NotifyUpdateApplied::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.softwareVersion, + commandData); + } + break; + } + case Commands::QueryImage::Id: { + Commands::QueryImage::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.vendorId, commandData.productId, + commandData.hardwareVersion, commandData.softwareVersion, to_underlying(commandData.protocolsSupported), + const_cast(Uint8::from_const_char(commandData.location.data())), commandData.requestorCanConsent, + commandData.metadataForProvider, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace OtaSoftwareUpdateProvider + +namespace OnOff { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::Off::Id: { + Commands::Off::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } + break; + } + case Commands::On::Id: { + Commands::On::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } + break; + } + case Commands::Toggle::Id: { + Commands::Toggle::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace OnOff + +namespace OperationalCredentials { + +void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) { // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. @@ -5291,10 +2006,72 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP { switch (aCommandPath.mCommandId) { - case Commands::ChangeChannel::Id: { - Commands::ChangeChannel::DecodableType commandData; + case Commands::AttestationResponse::Id: { + expectArgumentCount = 2; + chip::ByteSpan AttestationElements; + chip::ByteSpan Signature; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(AttestationElements); + break; + case 1: + TLVUnpackError = aDataTlv.Get(Signature); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + { + wasHandled = emberAfOperationalCredentialsClusterAttestationResponseCallback(aCommandPath.mEndpointId, apCommandObj, + AttestationElements, Signature); + } + break; + } + case Commands::CertificateChainResponse::Id: { expectArgumentCount = 1; - const uint8_t * match; + chip::ByteSpan Certificate; bool argExists[1]; memset(argExists, 0, sizeof argExists); @@ -5325,8 +2102,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(match); + TLVUnpackError = aDataTlv.Get(Certificate); break; default: // Unsupported tag, ignore it. @@ -5347,17 +2123,17 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { - wasHandled = emberAfTvChannelClusterChangeChannelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - const_cast(match), commandData); + wasHandled = emberAfOperationalCredentialsClusterCertificateChainResponseCallback(aCommandPath.mEndpointId, + apCommandObj, Certificate); } break; } - case Commands::ChangeChannelByNumber::Id: { - Commands::ChangeChannelByNumber::DecodableType commandData; - expectArgumentCount = 2; - uint16_t majorNumber; - uint16_t minorNumber; - bool argExists[2]; + case Commands::NOCResponse::Id: { + expectArgumentCount = 3; + uint8_t StatusCode; + uint8_t FabricIndex; + chip::ByteSpan DebugText; + bool argExists[3]; memset(argExists, 0, sizeof argExists); @@ -5370,7 +2146,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) + if (currentDecodeTagId < 3) { if (argExists[currentDecodeTagId]) { @@ -5387,10 +2163,13 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(majorNumber); + TLVUnpackError = aDataTlv.Get(StatusCode); break; case 1: - TLVUnpackError = aDataTlv.Get(minorNumber); + TLVUnpackError = aDataTlv.Get(FabricIndex); + break; + case 2: + TLVUnpackError = aDataTlv.Get(DebugText); break; default: // Unsupported tag, ignore it. @@ -5409,18 +2188,18 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { - wasHandled = emberAfTvChannelClusterChangeChannelByNumberCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, majorNumber, minorNumber, commandData); + wasHandled = emberAfOperationalCredentialsClusterNOCResponseCallback(aCommandPath.mEndpointId, apCommandObj, + StatusCode, FabricIndex, DebugText); } break; } - case Commands::SkipChannel::Id: { - Commands::SkipChannel::DecodableType commandData; - expectArgumentCount = 1; - uint16_t Count; - bool argExists[1]; + case Commands::OpCSRResponse::Id: { + expectArgumentCount = 2; + chip::ByteSpan NOCSRElements; + chip::ByteSpan AttestationSignature; + bool argExists[2]; memset(argExists, 0, sizeof argExists); @@ -5433,7 +2212,7 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP continue; } currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) + if (currentDecodeTagId < 2) { if (argExists[currentDecodeTagId]) { @@ -5450,7 +2229,10 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP switch (currentDecodeTagId) { case 0: - TLVUnpackError = aDataTlv.Get(Count); + TLVUnpackError = aDataTlv.Get(NOCSRElements); + break; + case 1: + TLVUnpackError = aDataTlv.Get(AttestationSignature); break; default: // Unsupported tag, ignore it. @@ -5469,10 +2251,10 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP TLVError = CHIP_NO_ERROR; } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { - wasHandled = emberAfTvChannelClusterSkipChannelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, Count, - commandData); + wasHandled = emberAfOperationalCredentialsClusterOpCSRResponseCallback(aCommandPath.mEndpointId, apCommandObj, + NOCSRElements, AttestationSignature); } break; } @@ -5499,9 +2281,9 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } -} // namespace TvChannel +} // namespace OperationalCredentials -namespace TargetNavigator { +namespace OperationalCredentials { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) { @@ -5509,77 +2291,205 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { - case Commands::NavigateTarget::Id: { - Commands::NavigateTarget::DecodableType commandData; - expectArgumentCount = 2; - uint8_t target; - const uint8_t * data; - bool argExists[2]; + case Commands::AddNOC::Id: { + Commands::AddNOC::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); + } + break; + } + case Commands::AddTrustedRootCertificate::Id: { + Commands::AddTrustedRootCertificate::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); + } + break; + } + case Commands::AttestationRequest::Id: { + Commands::AttestationRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); + } + break; + } + case Commands::CertificateChainRequest::Id: { + Commands::CertificateChainRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); + } + break; + } + case Commands::OpCSRRequest::Id: { + Commands::OpCSRRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); + } + break; + } + case Commands::RemoveFabric::Id: { + Commands::RemoveFabric::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); + } + break; + } + case Commands::RemoveTrustedRootCertificate::Id: { + Commands::RemoveTrustedRootCertificate::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); + } + break; + } + case Commands::UpdateFabricLabel::Id: { + Commands::UpdateFabricLabel::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); + } + break; + } + case Commands::UpdateNOC::Id: { + Commands::UpdateNOC::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } - memset(argExists, 0, sizeof argExists); + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) +} // namespace OperationalCredentials + +namespace TvChannel { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::ChangeChannel::Id: { + Commands::ChangeChannel::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(target); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(data); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } + wasHandled = emberAfTvChannelClusterChangeChannelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.match.data())), commandData); } - - if (CHIP_END_OF_TLV == TLVError) + break; + } + case Commands::ChangeChannelByNumber::Id: { + Commands::ChangeChannelByNumber::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; + wasHandled = emberAfTvChannelClusterChangeChannelByNumberCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.majorNumber, + commandData.minorNumber, commandData); + } + break; + } + case Commands::SkipChannel::Id: { + Commands::SkipChannel::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfTvChannelClusterSkipChannelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.count, commandData); } + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aCommandPath); + return; + } + } + } - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace TvChannel + +namespace TargetNavigator { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::NavigateTarget::Id: { + Commands::NavigateTarget::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfTargetNavigatorClusterNavigateTargetCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, target, const_cast(data), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.target, + const_cast(Uint8::from_const_char(commandData.data.data())), commandData); } break; } @@ -5591,18 +2501,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5617,8 +2520,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AccountLogin::Id: @@ -5691,8 +2592,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/tv-casting-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/tv-casting-app/zap-generated/IMClusterCommandHandler.cpp index 56c6d37b5d71f0..2ccdc844fc7733 100644 --- a/zzz_generated/tv-casting-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/tv-casting-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,80 +121,29 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::BarrierControlGoToPercent::Id: { Commands::BarrierControlGoToPercent::DecodableType commandData; - expectArgumentCount = 1; - uint8_t percentOpen; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(percentOpen); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfBarrierControlClusterBarrierControlGoToPercentCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, percentOpen, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.percentOpen, commandData); } break; } case Commands::BarrierControlStop::Id: { Commands::BarrierControlStop::DecodableType commandData; - - wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -331,18 +154,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -365,156 +181,30 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Bind::Id: { Commands::Bind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(nodeId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); } break; } case Commands::Unbind::Id: { Commands::Unbind::DecodableType commandData; - expectArgumentCount = 4; - chip::NodeId nodeId; - chip::GroupId groupId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(nodeId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(endpointId); - break; - case 3: - TLVUnpackError = aDataTlv.Get(clusterId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, - groupId, endpointId, clusterId, commandData); + wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.nodeId, commandData.groupId, commandData.endpointId, + commandData.clusterId, commandData); } break; } @@ -526,18 +216,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -551,1067 +234,164 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::MoveColor::Id: { Commands::MoveColor::DecodableType commandData; - expectArgumentCount = 4; - int16_t rateX; - int16_t rateY; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(rateX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rateY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterMoveColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - rateX, rateY, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rateX, commandData.rateY, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveColorTemperature::Id: { Commands::MoveColorTemperature::DecodableType commandData; - expectArgumentCount = 6; - uint8_t moveMode; - uint16_t rate; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, rate, colorTemperatureMinimum, - colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, commandData.optionsMask, + commandData.optionsOverride, commandData); } break; } case Commands::MoveHue::Id: { Commands::MoveHue::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfColorControlClusterMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveSaturation::Id: { Commands::MoveSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterMoveSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColor::Id: { Commands::MoveToColor::DecodableType commandData; - expectArgumentCount = 5; - uint16_t colorX; - uint16_t colorY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(colorY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveToColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - colorX, colorY, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterMoveToColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorX, commandData.colorY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToColorTemperature::Id: { Commands::MoveToColorTemperature::DecodableType commandData; - expectArgumentCount = 4; - uint16_t colorTemperature; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(colorTemperature); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, colorTemperature, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.colorTemperature, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHue::Id: { Commands::MoveToHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t direction; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(direction); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterMoveToHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, - direction, transitionTime, optionsMask, optionsOverride, - commandData); + wasHandled = emberAfColorControlClusterMoveToHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, to_underlying(commandData.direction), + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToHueAndSaturation::Id: { Commands::MoveToHueAndSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t hue; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(hue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToHueAndSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, saturation, transitionTime, optionsMask, - optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.hue, commandData.saturation, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::MoveToSaturation::Id: { Commands::MoveToSaturation::DecodableType commandData; - expectArgumentCount = 4; - uint8_t saturation; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(saturation); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterMoveToSaturationCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, saturation, transitionTime, optionsMask, optionsOverride, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.saturation, commandData.transitionTime, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColor::Id: { Commands::StepColor::DecodableType commandData; - expectArgumentCount = 5; - int16_t stepX; - int16_t stepY; - uint16_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepX); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepY); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = - emberAfColorControlClusterStepColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepX, stepY, - transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepColorCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.stepX, commandData.stepY, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepColorTemperature::Id: { Commands::StepColorTemperature::DecodableType commandData; - expectArgumentCount = 7; - uint8_t stepMode; - uint16_t stepSize; - uint16_t transitionTime; - uint16_t colorTemperatureMinimum; - uint16_t colorTemperatureMaximum; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - break; - case 4: - TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - break; - case 5: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 6: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStepColorTemperatureCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, transitionTime, - colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.colorTemperatureMinimum, commandData.colorTemperatureMaximum, + commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepHue::Id: { Commands::StepHue::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfColorControlClusterStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, - stepSize, transitionTime, optionsMask, optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepHueCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StepSaturation::Id: { Commands::StepSaturation::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint8_t transitionTime; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = emberAfColorControlClusterStepSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, optionsMask, - optionsOverride, commandData); + wasHandled = emberAfColorControlClusterStepSaturationCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionsMask, commandData.optionsOverride, commandData); } break; } case Commands::StopMoveStep::Id: { Commands::StopMoveStep::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionsMask; - uint8_t optionsOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionsMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionsOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfColorControlClusterStopMoveStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionsMask, optionsOverride, commandData); + commandData.optionsMask, commandData.optionsOverride, + commandData); } break; } @@ -1623,18 +403,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1648,81 +421,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::RetrieveLogsRequest::Id: { Commands::RetrieveLogsRequest::DecodableType commandData; - expectArgumentCount = 3; - uint8_t intent; - uint8_t requestedProtocol; - chip::ByteSpan transferFileDesignator; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(intent); - break; - case 1: - TLVUnpackError = aDataTlv.Get(requestedProtocol); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transferFileDesignator); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, - commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.intent), + to_underlying(commandData.requestedProtocol), commandData.transferFileDesignator, commandData); } break; } @@ -1734,18 +445,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1759,1385 +463,246 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ClearAllPins::Id: { Commands::ClearAllPins::DecodableType commandData; - - wasHandled = - emberAfDoorLockClusterClearAllPinsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfDoorLockClusterClearAllPinsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::ClearAllRfids::Id: { Commands::ClearAllRfids::DecodableType commandData; - - wasHandled = - emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfDoorLockClusterClearAllRfidsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::ClearHolidaySchedule::Id: { Commands::ClearHolidaySchedule::DecodableType commandData; - expectArgumentCount = 1; - uint8_t scheduleId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterClearHolidayScheduleCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, scheduleId, commandData); + wasHandled = emberAfDoorLockClusterClearHolidayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData); } break; } case Commands::ClearPin::Id: { Commands::ClearPin::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::ClearRfid::Id: { Commands::ClearRfid::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::ClearWeekdaySchedule::Id: { Commands::ClearWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterClearWeekdayScheduleCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, userId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::ClearYeardaySchedule::Id: { Commands::ClearYeardaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterClearYeardayScheduleCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, userId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::GetHolidaySchedule::Id: { Commands::GetHolidaySchedule::DecodableType commandData; - expectArgumentCount = 1; - uint8_t scheduleId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterGetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, commandData); + commandData.scheduleId, commandData); } break; } case Commands::GetLogRecord::Id: { Commands::GetLogRecord::DecodableType commandData; - expectArgumentCount = 1; - uint16_t logIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(logIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfDoorLockClusterGetLogRecordCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - logIndex, commandData); + commandData.logIndex, commandData); } break; } case Commands::GetPin::Id: { Commands::GetPin::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = - emberAfDoorLockClusterGetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, commandData); + wasHandled = emberAfDoorLockClusterGetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetRfid::Id: { Commands::GetRfid::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetUserType::Id: { Commands::GetUserType::DecodableType commandData; - expectArgumentCount = 1; - uint16_t userId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - commandData); + wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, commandData); } break; } case Commands::GetWeekdaySchedule::Id: { Commands::GetWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterGetWeekdayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, commandData); + wasHandled = emberAfDoorLockClusterGetWeekdayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::GetYeardaySchedule::Id: { Commands::GetYeardaySchedule::DecodableType commandData; - expectArgumentCount = 2; - uint8_t scheduleId; - uint16_t userId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterGetYeardayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, commandData); + wasHandled = emberAfDoorLockClusterGetYeardayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, commandData); } break; } case Commands::LockDoor::Id: { Commands::LockDoor::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan PIN; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(PIN); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) - { - wasHandled = - emberAfDoorLockClusterLockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, PIN, commandData); + wasHandled = emberAfDoorLockClusterLockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.pin, commandData); } break; } case Commands::SetHolidaySchedule::Id: { Commands::SetHolidaySchedule::DecodableType commandData; - expectArgumentCount = 4; - uint8_t scheduleId; - uint32_t localStartTime; - uint32_t localEndTime; - uint8_t operatingModeDuringHoliday; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(localStartTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(localEndTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, localStartTime, localEndTime, - operatingModeDuringHoliday, commandData); + wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.localStartTime, + commandData.localEndTime, commandData.operatingModeDuringHoliday, commandData); } break; } case Commands::SetPin::Id: { Commands::SetPin::DecodableType commandData; - expectArgumentCount = 4; - uint16_t userId; - uint8_t userStatus; - uint8_t userType; - chip::ByteSpan pin; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userStatus); - break; - case 2: - TLVUnpackError = aDataTlv.Get(userType); - break; - case 3: - TLVUnpackError = aDataTlv.Get(pin); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userStatus, userType, pin, commandData); + wasHandled = emberAfDoorLockClusterSetPinCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.userId, to_underlying(commandData.userStatus), + to_underlying(commandData.userType), commandData.pin, commandData); } break; } case Commands::SetRfid::Id: { Commands::SetRfid::DecodableType commandData; - expectArgumentCount = 4; - uint16_t userId; - uint8_t userStatus; - uint8_t userType; - chip::ByteSpan id; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userStatus); - break; - case 2: - TLVUnpackError = aDataTlv.Get(userType); - break; - case 3: - TLVUnpackError = aDataTlv.Get(id); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userStatus, userType, id, commandData); + wasHandled = emberAfDoorLockClusterSetRfidCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.userId, to_underlying(commandData.userStatus), + to_underlying(commandData.userType), commandData.id, commandData); } break; } case Commands::SetUserType::Id: { Commands::SetUserType::DecodableType commandData; - expectArgumentCount = 2; - uint16_t userId; - uint8_t userType; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, - userType, commandData); + wasHandled = + emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.userId, to_underlying(commandData.userType), commandData); } break; } case Commands::SetWeekdaySchedule::Id: { Commands::SetWeekdaySchedule::DecodableType commandData; - expectArgumentCount = 7; - uint8_t scheduleId; - uint16_t userId; - uint8_t daysMask; - uint8_t startHour; - uint8_t startMinute; - uint8_t endHour; - uint8_t endMinute; - bool argExists[7]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 7) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(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: - TLVUnpackError = aDataTlv.Get(startMinute); - break; - case 5: - TLVUnpackError = aDataTlv.Get(endHour); - break; - case 6: - TLVUnpackError = aDataTlv.Get(endMinute); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) - { - wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, daysMask, startHour, startMinute, - endHour, endMinute, commandData); + wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, + commandData.daysMask, commandData.startHour, commandData.startMinute, commandData.endHour, + commandData.endMinute, commandData); } break; } case Commands::SetYeardaySchedule::Id: { Commands::SetYeardaySchedule::DecodableType commandData; - expectArgumentCount = 4; - uint8_t scheduleId; - uint16_t userId; - uint32_t localStartTime; - uint32_t localEndTime; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(scheduleId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(userId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(localStartTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(localEndTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfDoorLockClusterSetYeardayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - scheduleId, userId, localStartTime, localEndTime, commandData); + wasHandled = emberAfDoorLockClusterSetYeardayScheduleCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.scheduleId, commandData.userId, + commandData.localStartTime, commandData.localEndTime, commandData); } break; } case Commands::UnlockDoor::Id: { Commands::UnlockDoor::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan PIN; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(PIN); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, PIN, - commandData); + wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.pin, commandData); } break; } case Commands::UnlockWithTimeout::Id: { Commands::UnlockWithTimeout::DecodableType commandData; - expectArgumentCount = 2; - uint16_t timeoutInSeconds; - chip::ByteSpan pin; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutInSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(pin); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - timeoutInSeconds, pin, commandData); + wasHandled = + emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.timeoutInSeconds, commandData.pin, commandData); } break; } @@ -3149,18 +714,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3174,161 +732,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -3340,18 +778,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3365,334 +796,70 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddGroup::Id: { Commands::AddGroup::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - const uint8_t * groupName; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(groupName); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - const_cast(groupName), commandData); + wasHandled = emberAfGroupsClusterAddGroupCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, + const_cast(Uint8::from_const_char(commandData.groupName.data())), commandData); } break; } case Commands::AddGroupIfIdentifying::Id: { Commands::AddGroupIfIdentifying::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - const uint8_t * groupName; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(groupName); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGroupsClusterAddGroupIfIdentifyingCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, const_cast(groupName), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, + const_cast(Uint8::from_const_char(commandData.groupName.data())), commandData); } break; } case Commands::GetGroupMembership::Id: { Commands::GetGroupMembership::DecodableType commandData; - expectArgumentCount = 2; - uint8_t groupCount; - /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupCount); - break; - case 1: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupCount, groupList, commandData); + commandData.groupCount, nullptr, commandData); } break; } case Commands::RemoveAllGroups::Id: { Commands::RemoveAllGroups::DecodableType commandData; - - wasHandled = - emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::RemoveGroup::Id: { Commands::RemoveGroup::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - commandData); + wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData); } break; } case Commands::ViewGroup::Id: { Commands::ViewGroup::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - commandData); + wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData); } break; } @@ -3704,18 +871,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3729,76 +889,19 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ZoneEnrollResponse::Id: { Commands::ZoneEnrollResponse::DecodableType commandData; - expectArgumentCount = 2; - uint8_t enrollResponseCode; - uint8_t zoneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(enrollResponseCode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(zoneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfIasZoneClusterZoneEnrollResponseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - enrollResponseCode, zoneId, commandData); + to_underlying(commandData.enrollResponseCode), + commandData.zoneId, commandData); } break; } @@ -3810,18 +913,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3835,80 +931,29 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Identify::Id: { Commands::Identify::DecodableType commandData; - expectArgumentCount = 1; - uint16_t identifyTime; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(identifyTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - identifyTime, commandData); + commandData.identifyTime, commandData); } break; } case Commands::IdentifyQuery::Id: { Commands::IdentifyQuery::DecodableType commandData; - - wasHandled = - emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfIdentifyClusterIdentifyQueryCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -3919,18 +964,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -3944,502 +982,96 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Move::Id: { Commands::Move::DecodableType commandData; - expectArgumentCount = 4; - uint8_t moveMode; - uint8_t rate; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, - rate, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.moveMode), commandData.rate, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevel::Id: { Commands::MoveToLevel::DecodableType commandData; - expectArgumentCount = 4; - uint8_t level; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 2: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.level, commandData.transitionTime, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::MoveToLevelWithOnOff::Id: { Commands::MoveToLevelWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t level; - uint16_t transitionTime; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(level); - break; - case 1: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, level, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData.level, + commandData.transitionTime, commandData); } break; } case Commands::MoveWithOnOff::Id: { Commands::MoveWithOnOff::DecodableType commandData; - expectArgumentCount = 2; - uint8_t moveMode; - uint8_t rate; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(moveMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(rate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - moveMode, rate, commandData); + to_underlying(commandData.moveMode), commandData.rate, + commandData); } break; } case Commands::Step::Id: { Commands::Step::DecodableType commandData; - expectArgumentCount = 5; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 4: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) - { - wasHandled = - emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, - transitionTime, optionMask, optionOverride, commandData); + wasHandled = emberAfLevelControlClusterStepCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StepWithOnOff::Id: { Commands::StepWithOnOff::DecodableType commandData; - expectArgumentCount = 3; - uint8_t stepMode; - uint8_t stepSize; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(stepMode); - break; - case 1: - TLVUnpackError = aDataTlv.Get(stepSize); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) - { - wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - stepMode, stepSize, transitionTime, commandData); + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.stepMode), commandData.stepSize, + commandData.transitionTime, commandData); } break; - } - case Commands::Stop::Id: { - Commands::Stop::DecodableType commandData; - expectArgumentCount = 2; - uint8_t optionMask; - uint8_t optionOverride; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(optionMask); - break; - case 1: - TLVUnpackError = aDataTlv.Get(optionOverride); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + } + case Commands::Stop::Id: { + Commands::Stop::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - optionMask, optionOverride, commandData); + wasHandled = + emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.optionMask, commandData.optionOverride, commandData); } break; } case Commands::StopWithOnOff::Id: { Commands::StopWithOnOff::DecodableType commandData; - - wasHandled = - emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -4450,18 +1082,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -4475,624 +1100,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -5104,18 +1211,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5129,230 +1229,43 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ApplyUpdateRequest::Id: { Commands::ApplyUpdateRequest::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t newVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(newVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, newVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.newVersion, + commandData); } break; } case Commands::NotifyUpdateApplied::Id: { Commands::NotifyUpdateApplied::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan updateToken; - uint32_t softwareVersion; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(updateToken); - break; - case 1: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, updateToken, softwareVersion, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.updateToken, commandData.softwareVersion, + commandData); } break; } case Commands::QueryImage::Id: { Commands::QueryImage::DecodableType commandData; - expectArgumentCount = 8; - uint16_t vendorId; - uint16_t productId; - uint16_t hardwareVersion; - uint32_t softwareVersion; - uint8_t protocolsSupported; - const uint8_t * location; - bool requestorCanConsent; - chip::ByteSpan metadataForProvider; - bool argExists[8]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 8) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(vendorId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(productId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(hardwareVersion); - break; - case 3: - TLVUnpackError = aDataTlv.Get(softwareVersion); - break; - case 4: - TLVUnpackError = aDataTlv.Get(protocolsSupported); - break; - case 5: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(location); - break; - case 6: - TLVUnpackError = aDataTlv.Get(requestorCanConsent); - break; - case 7: - TLVUnpackError = aDataTlv.Get(metadataForProvider); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, vendorId, productId, hardwareVersion, softwareVersion, - protocolsSupported, const_cast(location), requestorCanConsent, metadataForProvider, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.vendorId, commandData.productId, + commandData.hardwareVersion, commandData.softwareVersion, to_underlying(commandData.protocolsSupported), + const_cast(Uint8::from_const_char(commandData.location.data())), commandData.requestorCanConsent, + commandData.metadataForProvider, commandData); } break; } @@ -5364,18 +1277,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5389,31 +1295,36 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Off::Id: { Commands::Off::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::On::Id: { Commands::On::DecodableType commandData; - - wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::Toggle::Id: { Commands::Toggle::DecodableType commandData; - - wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -5424,18 +1335,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -5449,574 +1353,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -6028,18 +1458,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6053,471 +1476,81 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddScene::Id: { Commands::AddScene::DecodableType commandData; - expectArgumentCount = 5; - uint16_t groupId; - uint8_t sceneId; - uint16_t transitionTime; - const uint8_t * sceneName; - /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - case 3: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - break; - case 4: - // Just for compatibility, we will add array type support in IM later. - TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterAddSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, transitionTime, const_cast(sceneName), - extensionFieldSets, commandData); + wasHandled = emberAfScenesClusterAddSceneCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.groupId, commandData.sceneId, + commandData.transitionTime, const_cast(Uint8::from_const_char(commandData.sceneName.data())), + nullptr, commandData); } break; } case Commands::GetSceneMembership::Id: { Commands::GetSceneMembership::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupId, commandData); + commandData.groupId, commandData); } break; } case Commands::RecallScene::Id: { Commands::RecallScene::DecodableType commandData; - expectArgumentCount = 3; - uint16_t groupId; - uint8_t sceneId; - uint16_t transitionTime; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - case 2: - TLVUnpackError = aDataTlv.Get(transitionTime); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, transitionTime, commandData); + wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, + commandData.transitionTime, commandData); } break; } case Commands::RemoveAllScenes::Id: { Commands::RemoveAllScenes::DecodableType commandData; - expectArgumentCount = 1; - uint16_t groupId; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - groupId, commandData); + commandData.groupId, commandData); } break; } case Commands::RemoveScene::Id: { Commands::RemoveScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } case Commands::StoreScene::Id: { Commands::StoreScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } case Commands::ViewScene::Id: { Commands::ViewScene::DecodableType commandData; - expectArgumentCount = 2; - uint16_t groupId; - uint8_t sceneId; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(groupId); - break; - case 1: - TLVUnpackError = aDataTlv.Get(sceneId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { - wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, - sceneId, commandData); + wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData.groupId, commandData.sceneId, commandData); } break; } @@ -6529,18 +1562,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6554,33 +1580,39 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::Test::Id: { Commands::Test::DecodableType commandData; - - wasHandled = emberAfTestClusterClusterTestCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfTestClusterClusterTestCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } case Commands::TestNotHandled::Id: { Commands::TestNotHandled::DecodableType commandData; - - wasHandled = - emberAfTestClusterClusterTestNotHandledCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfTestClusterClusterTestNotHandledCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } case Commands::TestSpecific::Id: { Commands::TestSpecific::DecodableType commandData; - - wasHandled = - emberAfTestClusterClusterTestSpecificCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfTestClusterClusterTestSpecificCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } default: { @@ -6591,18 +1623,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -6617,8 +1642,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -6682,8 +1705,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); } diff --git a/zzz_generated/window-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/window-app/zap-generated/IMClusterCommandHandler.cpp index 4b111280fae7b3..d2965d0bb2733c 100644 --- a/zzz_generated/window-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/window-app/zap-generated/IMClusterCommandHandler.cpp @@ -26,8 +26,9 @@ #include #include #include - #include +#include +#include // Currently we need some work to keep compatible with ember lib. #include @@ -57,161 +58,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::OpenBasicCommissioningWindow::Id: { Commands::OpenBasicCommissioningWindow::DecodableType commandData; - expectArgumentCount = 1; - uint16_t CommissioningTimeout; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, commandData); } break; } case Commands::OpenCommissioningWindow::Id: { Commands::OpenCommissioningWindow::DecodableType commandData; - expectArgumentCount = 6; - uint16_t CommissioningTimeout; - chip::ByteSpan PAKEVerifier; - uint16_t Discriminator; - uint32_t Iterations; - chip::ByteSpan Salt; - uint16_t PasscodeID; - bool argExists[6]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 6) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CommissioningTimeout); - break; - case 1: - TLVUnpackError = aDataTlv.Get(PAKEVerifier); - break; - case 2: - TLVUnpackError = aDataTlv.Get(Discriminator); - break; - case 3: - TLVUnpackError = aDataTlv.Get(Iterations); - break; - case 4: - TLVUnpackError = aDataTlv.Get(Salt); - break; - case 5: - TLVUnpackError = aDataTlv.Get(PasscodeID); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, - Iterations, Salt, PasscodeID, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.commissioningTimeout, + commandData.pAKEVerifier, commandData.discriminator, commandData.iterations, commandData.salt, + commandData.passcodeID, commandData); } break; } case Commands::RevokeCommissioning::Id: { Commands::RevokeCommissioning::DecodableType commandData; - - wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -222,18 +103,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -247,161 +121,41 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::ArmFailSafe::Id: { Commands::ArmFailSafe::DecodableType commandData; - expectArgumentCount = 3; - uint16_t expiryLengthSeconds; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.expiryLengthSeconds, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::CommissioningComplete::Id: { Commands::CommissioningComplete::DecodableType commandData; - - wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, - aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, + aCommandPath.mEndpointId, commandData); + } break; } case Commands::SetRegulatoryConfig::Id: { Commands::SetRegulatoryConfig::DecodableType commandData; - expectArgumentCount = 4; - uint8_t location; - const uint8_t * countryCode; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(location); - break; - case 1: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(countryCode); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast(countryCode), breadcrumb, - timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, to_underlying(commandData.location), + const_cast(Uint8::from_const_char(commandData.countryCode.data())), commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } @@ -413,18 +167,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -438,624 +185,106 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddThreadNetwork::Id: { Commands::AddThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::AddWiFiNetwork::Id: { Commands::AddWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } case Commands::DisableNetwork::Id: { Commands::DisableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::EnableNetwork::Id: { Commands::EnableNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan networkID; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(networkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, networkID, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::GetLastNetworkCommissioningResult::Id: { Commands::GetLastNetworkCommissioningResult::DecodableType commandData; - expectArgumentCount = 1; - uint32_t timeoutMs; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.timeoutMs, commandData); } break; } case Commands::RemoveNetwork::Id: { Commands::RemoveNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan NetworkID; - uint64_t Breadcrumb; - uint32_t TimeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NetworkID); - break; - case 1: - TLVUnpackError = aDataTlv.Get(Breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(TimeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NetworkID, Breadcrumb, TimeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.networkID, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::ScanNetworks::Id: { Commands::ScanNetworks::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan ssid; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateThreadNetwork::Id: { Commands::UpdateThreadNetwork::DecodableType commandData; - expectArgumentCount = 3; - chip::ByteSpan operationalDataset; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[3]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 3) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(operationalDataset); - break; - case 1: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 2: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, operationalDataset, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.operationalDataset, commandData.breadcrumb, + commandData.timeoutMs, commandData); } break; } case Commands::UpdateWiFiNetwork::Id: { Commands::UpdateWiFiNetwork::DecodableType commandData; - expectArgumentCount = 4; - chip::ByteSpan ssid; - chip::ByteSpan credentials; - uint64_t breadcrumb; - uint32_t timeoutMs; - bool argExists[4]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 4) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(ssid); - break; - case 1: - TLVUnpackError = aDataTlv.Get(credentials); - break; - case 2: - TLVUnpackError = aDataTlv.Get(breadcrumb); - break; - case 3: - TLVUnpackError = aDataTlv.Get(timeoutMs); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, ssid, credentials, breadcrumb, timeoutMs, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.ssid, commandData.credentials, + commandData.breadcrumb, commandData.timeoutMs, commandData); } break; } @@ -1067,18 +296,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1092,574 +314,100 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::AddNOC::Id: { Commands::AddNOC::DecodableType commandData; - expectArgumentCount = 5; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - chip::ByteSpan IPKValue; - chip::NodeId CaseAdminNode; - uint16_t AdminVendorId; - bool argExists[5]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 5) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - case 2: - TLVUnpackError = aDataTlv.Get(IPKValue); - break; - case 3: - TLVUnpackError = aDataTlv.Get(CaseAdminNode); - break; - case 4: - TLVUnpackError = aDataTlv.Get(AdminVendorId); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, - AdminVendorId, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, + commandData.iPKValue, commandData.caseAdminNode, commandData.adminVendorId, commandData); } break; } case Commands::AddTrustedRootCertificate::Id: { Commands::AddTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan RootCertificate; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(RootCertificate); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, RootCertificate, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.rootCertificate, commandData); } break; } case Commands::AttestationRequest::Id: { Commands::AttestationRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan AttestationNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(AttestationNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, AttestationNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.attestationNonce, commandData); } break; } case Commands::CertificateChainRequest::Id: { Commands::CertificateChainRequest::DecodableType commandData; - expectArgumentCount = 1; - uint8_t CertificateType; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CertificateType); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CertificateType, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.certificateType, commandData); } break; } case Commands::OpCSRRequest::Id: { Commands::OpCSRRequest::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan CSRNonce; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(CSRNonce); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, CSRNonce, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.cSRNonce, commandData); } break; } case Commands::RemoveFabric::Id: { Commands::RemoveFabric::DecodableType commandData; - expectArgumentCount = 1; - uint8_t FabricIndex; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(FabricIndex); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, FabricIndex, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.fabricIndex, commandData); } break; } case Commands::RemoveTrustedRootCertificate::Id: { Commands::RemoveTrustedRootCertificate::DecodableType commandData; - expectArgumentCount = 1; - chip::ByteSpan TrustedRootIdentifier; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(TrustedRootIdentifier); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, TrustedRootIdentifier, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.trustedRootIdentifier, commandData); } break; } case Commands::UpdateFabricLabel::Id: { Commands::UpdateFabricLabel::DecodableType commandData; - expectArgumentCount = 1; - const uint8_t * Label; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(Label); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast(Label), commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, + const_cast(Uint8::from_const_char(commandData.label.data())), commandData); } break; } case Commands::UpdateNOC::Id: { Commands::UpdateNOC::DecodableType commandData; - expectArgumentCount = 2; - chip::ByteSpan NOCValue; - chip::ByteSpan ICACValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(NOCValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(ICACValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.nOCValue, commandData.iCACValue, commandData); } break; } @@ -1671,18 +419,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -1696,282 +437,81 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP // When TLVError is CHIP_END_OF_TLV, it means 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; + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; { switch (aCommandPath.mCommandId) { case Commands::DownOrClose::Id: { Commands::DownOrClose::DecodableType commandData; - - wasHandled = - emberAfWindowCoveringClusterDownOrCloseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfWindowCoveringClusterDownOrCloseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } case Commands::GoToLiftPercentage::Id: { Commands::GoToLiftPercentage::DecodableType commandData; - expectArgumentCount = 2; - uint8_t liftPercentageValue; - uint16_t liftPercent100thsValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(liftPercentageValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(liftPercent100thsValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfWindowCoveringClusterGoToLiftPercentageCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, liftPercentageValue, liftPercent100thsValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.liftPercentageValue, + commandData.liftPercent100thsValue, commandData); } break; } case Commands::GoToLiftValue::Id: { Commands::GoToLiftValue::DecodableType commandData; - expectArgumentCount = 1; - uint16_t liftValue; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(liftValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfWindowCoveringClusterGoToLiftValueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - liftValue, commandData); + commandData.liftValue, commandData); } break; } case Commands::GoToTiltPercentage::Id: { Commands::GoToTiltPercentage::DecodableType commandData; - expectArgumentCount = 2; - uint8_t tiltPercentageValue; - uint16_t tiltPercent100thsValue; - bool argExists[2]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 2) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(tiltPercentageValue); - break; - case 1: - TLVUnpackError = aDataTlv.Get(tiltPercent100thsValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfWindowCoveringClusterGoToTiltPercentageCallback( - apCommandObj, aCommandPath, aCommandPath.mEndpointId, tiltPercentageValue, tiltPercent100thsValue, commandData); + apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData.tiltPercentageValue, + commandData.tiltPercent100thsValue, commandData); } break; } case Commands::GoToTiltValue::Id: { Commands::GoToTiltValue::DecodableType commandData; - expectArgumentCount = 1; - uint16_t tiltValue; - bool argExists[1]; - - memset(argExists, 0, sizeof argExists); - - while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) - { - // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. - // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. - if (!TLV::IsContextTag(aDataTlv.GetTag())) - { - continue; - } - currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); - if (currentDecodeTagId < 1) - { - if (argExists[currentDecodeTagId]) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - else - { - argExists[currentDecodeTagId] = true; - validArgumentCount++; - } - } - switch (currentDecodeTagId) - { - case 0: - TLVUnpackError = aDataTlv.Get(tiltValue); - break; - default: - // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (CHIP_NO_ERROR != TLVUnpackError) - { - break; - } - } - - if (CHIP_END_OF_TLV == TLVError) - { - // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. - TLVError = CHIP_NO_ERROR; - } - - if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) { wasHandled = emberAfWindowCoveringClusterGoToTiltValueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, - tiltValue, commandData); + commandData.tiltValue, commandData); } break; } case Commands::StopMotion::Id: { Commands::StopMotion::DecodableType commandData; - - wasHandled = - emberAfWindowCoveringClusterStopMotionCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfWindowCoveringClusterStopMotionCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, + commandData); + } break; } case Commands::UpOrOpen::Id: { Commands::UpOrOpen::DecodableType commandData; - - wasHandled = - emberAfWindowCoveringClusterUpOrOpenCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfWindowCoveringClusterUpOrOpenCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); + } break; } default: { @@ -1982,18 +522,11 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } } - if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + if (CHIP_NO_ERROR != TLVError || !wasHandled) { apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, - "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT - ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, - validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); - // A command with no arguments would never write currentDecodeTagId. If - // progress logging is also disabled, it would look unused. Silence that - // warning. - UNUSED_VAR(currentDecodeTagId); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); } } @@ -2008,8 +541,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); - TLV::TLVType dataTlvType; - SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aCommandPath.mClusterId) { case Clusters::AdministratorCommissioning::Id: @@ -2034,8 +565,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: break; } -exit: - aReader.ExitContainer(dataTlvType); Compatibility::ResetEmberAfObjects(); }