| /* |
| * |
| * Copyright (c) 2021 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // THIS FILE IS GENERATED BY ZAP |
| |
| #include <cinttypes> |
| #include <cstdint> |
| |
| #include "app/util/util.h" |
| #include <app-common/zap-generated/af-structs.h> |
| #include <app-common/zap-generated/callback.h> |
| #include <app-common/zap-generated/cluster-objects.h> |
| #include <app-common/zap-generated/ids/Clusters.h> |
| #include <app-common/zap-generated/ids/Commands.h> |
| |
| #include <app/InteractionModelEngine.h> |
| |
| // Currently we need some work to keep compatible with ember lib. |
| #include <app/util/ember-compatibility-functions.h> |
| |
| namespace chip { |
| namespace app { |
| |
| namespace { |
| void ReportCommandUnsupported(Command * aCommandObj, const ConcreteCommandPath & aCommandPath) |
| { |
| aCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, |
| Protocols::InteractionModel::Status::UnsupportedCommand); |
| ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, |
| ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); |
| } |
| } // anonymous namespace |
| |
| // Cluster specific command parsing |
| |
| namespace Clusters { |
| |
| namespace AdministratorCommissioning { |
| |
| 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::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) |
| { |
| wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, CommissioningTimeout, PAKEVerifier, Discriminator, |
| Iterations, Salt, PasscodeID, commandData); |
| } |
| break; |
| } |
| case Commands::RevokeCommissioning::Id: { |
| Commands::RevokeCommissioning::DecodableType commandData; |
| |
| wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(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 AdministratorCommissioning |
| |
| namespace BarrierControl { |
| |
| 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::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) |
| { |
| wasHandled = emberAfBarrierControlClusterBarrierControlGoToPercentCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, percentOpen, commandData); |
| } |
| break; |
| } |
| case Commands::BarrierControlStop::Id: { |
| Commands::BarrierControlStop::DecodableType commandData; |
| |
| wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(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 BarrierControl |
| |
| namespace Basic { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| } |
| |
| } // namespace Basic |
| |
| namespace Binding { |
| |
| 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::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) |
| { |
| wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, |
| groupId, endpointId, 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) |
| { |
| wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, nodeId, |
| groupId, endpointId, clusterId, 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 Binding |
| |
| namespace ColorControl { |
| |
| 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::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) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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); |
| } |
| 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) |
| { |
| wasHandled = |
| emberAfColorControlClusterEnhancedMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| moveMode, rate, optionsMask, 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) |
| { |
| wasHandled = emberAfColorControlClusterEnhancedMoveToHueCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, enhancedHue, direction, transitionTime, optionsMask, |
| 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) |
| { |
| wasHandled = emberAfColorControlClusterEnhancedMoveToHueAndSaturationCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, enhancedHue, saturation, transitionTime, optionsMask, |
| 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) |
| { |
| wasHandled = emberAfColorControlClusterEnhancedStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| stepMode, stepSize, transitionTime, optionsMask, |
| 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| rateX, rateY, optionsMask, 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveColorTemperatureCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, rate, colorTemperatureMinimum, |
| colorTemperatureMaximum, optionsMask, 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| moveMode, rate, optionsMask, 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) |
| { |
| wasHandled = |
| emberAfColorControlClusterMoveSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, moveMode, |
| rate, optionsMask, 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveToColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| colorX, colorY, transitionTime, optionsMask, |
| 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveToColorTemperatureCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, colorTemperature, transitionTime, optionsMask, |
| 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveToHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, |
| direction, transitionTime, optionsMask, 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveToHueAndSaturationCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, hue, saturation, transitionTime, optionsMask, |
| 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) |
| { |
| wasHandled = emberAfColorControlClusterMoveToSaturationCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, saturation, transitionTime, optionsMask, 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) |
| { |
| wasHandled = |
| emberAfColorControlClusterStepColorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepX, stepY, |
| transitionTime, optionsMask, 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) |
| { |
| wasHandled = emberAfColorControlClusterStepColorTemperatureCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, stepSize, transitionTime, |
| colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, 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) |
| { |
| wasHandled = |
| emberAfColorControlClusterStepHueCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, stepMode, |
| stepSize, transitionTime, optionsMask, 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) |
| { |
| wasHandled = emberAfColorControlClusterStepSaturationCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| stepMode, stepSize, transitionTime, optionsMask, |
| 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) |
| { |
| wasHandled = emberAfColorControlClusterStopMoveStepCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| optionsMask, optionsOverride, 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 ColorControl |
| |
| 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; |
| 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::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) |
| { |
| wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, intent, requestedProtocol, transferFileDesignator, |
| 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 DiagnosticLogs |
| |
| namespace DoorLock { |
| |
| 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::ClearAllPins::Id: { |
| Commands::ClearAllPins::DecodableType commandData; |
| |
| wasHandled = |
| emberAfDoorLockClusterClearAllPinsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); |
| break; |
| } |
| case Commands::ClearAllRfids::Id: { |
| Commands::ClearAllRfids::DecodableType commandData; |
| |
| 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) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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); |
| } |
| 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) |
| { |
| wasHandled = emberAfDoorLockClusterClearPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfDoorLockClusterClearRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfDoorLockClusterClearWeekdayScheduleCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, 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) |
| { |
| wasHandled = emberAfDoorLockClusterClearYeardayScheduleCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, scheduleId, 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) |
| { |
| wasHandled = emberAfDoorLockClusterGetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| 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) |
| { |
| wasHandled = emberAfDoorLockClusterGetLogRecordCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| 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) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, 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); |
| } |
| 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) |
| { |
| wasHandled = emberAfDoorLockClusterGetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfDoorLockClusterGetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| 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) |
| { |
| 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) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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); |
| } |
| 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) |
| { |
| wasHandled = emberAfDoorLockClusterSetHolidayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| scheduleId, localStartTime, localEndTime, |
| 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) |
| { |
| wasHandled = emberAfDoorLockClusterSetPinCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, |
| userStatus, userType, 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) |
| { |
| wasHandled = emberAfDoorLockClusterSetRfidCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, |
| userStatus, userType, 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) |
| { |
| wasHandled = emberAfDoorLockClusterSetUserTypeCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, userId, |
| 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) |
| { |
| wasHandled = emberAfDoorLockClusterSetWeekdayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| scheduleId, userId, daysMask, startHour, startMinute, |
| endHour, 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) |
| { |
| wasHandled = |
| emberAfDoorLockClusterSetYeardayScheduleCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| scheduleId, userId, localStartTime, 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) |
| { |
| wasHandled = emberAfDoorLockClusterUnlockDoorCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfDoorLockClusterUnlockWithTimeoutCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| timeoutInSeconds, pin, 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 DoorLock |
| |
| namespace EthernetNetworkDiagnostics { |
| |
| 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::ResetCounts::Id: { |
| Commands::ResetCounts::DecodableType commandData; |
| |
| wasHandled = emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(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 EthernetNetworkDiagnostics |
| |
| namespace GeneralCommissioning { |
| |
| 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::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) |
| { |
| wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, expiryLengthSeconds, breadcrumb, timeoutMs, 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) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, 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) |
| { |
| wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, location, const_cast<uint8_t *>(countryCode), 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 GeneralCommissioning |
| |
| namespace Groups { |
| |
| 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::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) |
| { |
| wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, |
| const_cast<uint8_t *>(groupName), 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) |
| { |
| wasHandled = emberAfGroupsClusterAddGroupIfIdentifyingCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, const_cast<uint8_t *>(groupName), 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<const uint8_t *&>(groupList)); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| groupCount, groupList, commandData); |
| } |
| break; |
| } |
| case Commands::RemoveAllGroups::Id: { |
| Commands::RemoveAllGroups::DecodableType commandData; |
| |
| 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) |
| { |
| wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, |
| 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 Groups |
| |
| namespace IasZone { |
| |
| 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::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) |
| { |
| wasHandled = emberAfIasZoneClusterZoneEnrollResponseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| enrollResponseCode, zoneId, 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 IasZone |
| |
| namespace Identify { |
| |
| 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::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) |
| { |
| wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| identifyTime, commandData); |
| } |
| break; |
| } |
| case Commands::IdentifyQuery::Id: { |
| Commands::IdentifyQuery::DecodableType commandData; |
| |
| wasHandled = |
| emberAfIdentifyClusterIdentifyQueryCallback(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 Identify |
| |
| 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 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<uint8_t *>(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 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::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) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, IPKValue, CaseAdminNode, |
| 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) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterAttestationRequestCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterCertificateChainRequestCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| 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); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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 = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, 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) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, const_cast<uint8_t *>(Label), 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) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback( |
| apCommandObj, aCommandPath, aCommandPath.mEndpointId, NOCValue, ICACValue, 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 OperationalCredentials |
| |
| namespace Scenes { |
| |
| 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::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<const uint8_t *&>(extensionFieldSets)); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) |
| { |
| wasHandled = emberAfScenesClusterAddSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, |
| sceneId, transitionTime, const_cast<uint8_t *>(sceneName), |
| extensionFieldSets, 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) |
| { |
| wasHandled = emberAfScenesClusterGetSceneMembershipCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| 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) |
| { |
| wasHandled = emberAfScenesClusterRecallSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, |
| sceneId, 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) |
| { |
| wasHandled = emberAfScenesClusterRemoveAllScenesCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| 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) |
| { |
| wasHandled = emberAfScenesClusterRemoveSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, |
| 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) |
| { |
| wasHandled = emberAfScenesClusterStoreSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, |
| 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) |
| { |
| wasHandled = emberAfScenesClusterViewSceneCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, groupId, |
| sceneId, 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 Scenes |
| |
| namespace SoftwareDiagnostics { |
| |
| 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::ResetWatermarks::Id: { |
| Commands::ResetWatermarks::DecodableType commandData; |
| |
| wasHandled = emberAfSoftwareDiagnosticsClusterResetWatermarksCallback(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 SoftwareDiagnostics |
| |
| namespace TestCluster { |
| |
| 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::Test::Id: { |
| Commands::Test::DecodableType commandData; |
| |
| 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) |
| { |
| wasHandled = emberAfTestClusterClusterTestAddArgumentsCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, |
| arg1, arg2, commandData); |
| } |
| break; |
| } |
| case Commands::TestNotHandled::Id: { |
| Commands::TestNotHandled::DecodableType commandData; |
| |
| wasHandled = |
| emberAfTestClusterClusterTestNotHandledCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); |
| break; |
| } |
| case Commands::TestSpecific::Id: { |
| Commands::TestSpecific::DecodableType commandData; |
| |
| wasHandled = |
| emberAfTestClusterClusterTestSpecificCallback(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 TestCluster |
| |
| namespace ThreadNetworkDiagnostics { |
| |
| 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::ResetCounts::Id: { |
| Commands::ResetCounts::DecodableType commandData; |
| |
| wasHandled = emberAfThreadNetworkDiagnosticsClusterResetCountsCallback(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 ThreadNetworkDiagnostics |
| |
| namespace WiFiNetworkDiagnostics { |
| |
| 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::ResetCounts::Id: { |
| Commands::ResetCounts::DecodableType commandData; |
| |
| wasHandled = emberAfWiFiNetworkDiagnosticsClusterResetCountsCallback(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 WiFiNetworkDiagnostics |
| |
| namespace WindowCovering { |
| |
| 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::DownOrClose::Id: { |
| Commands::DownOrClose::DecodableType commandData; |
| |
| wasHandled = |
| emberAfWindowCoveringClusterDownOrCloseCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); |
| break; |
| } |
| case Commands::StopMotion::Id: { |
| Commands::StopMotion::DecodableType commandData; |
| |
| wasHandled = |
| emberAfWindowCoveringClusterStopMotionCallback(apCommandObj, aCommandPath, aCommandPath.mEndpointId, commandData); |
| break; |
| } |
| case Commands::UpOrOpen::Id: { |
| Commands::UpOrOpen::DecodableType commandData; |
| |
| wasHandled = |
| emberAfWindowCoveringClusterUpOrOpenCallback(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 WindowCovering |
| |
| } // namespace Clusters |
| |
| void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aReader, CommandHandler * apCommandObj) |
| { |
| ChipLogDetail(Zcl, "Received Cluster Command: Endpoint=%" PRIx16 " Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI, |
| aCommandPath.mEndpointId, ChipLogValueMEI(aCommandPath.mClusterId), ChipLogValueMEI(aCommandPath.mCommandId)); |
| |
| Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); |
| |
| TLV::TLVType dataTlvType; |
| SuccessOrExit(aReader.EnterContainer(dataTlvType)); |
| switch (aCommandPath.mClusterId) |
| { |
| case Clusters::AdministratorCommissioning::Id: |
| Clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::BarrierControl::Id: |
| Clusters::BarrierControl::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::Basic::Id: |
| Clusters::Basic::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::Binding::Id: |
| Clusters::Binding::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::ColorControl::Id: |
| Clusters::ColorControl::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::DiagnosticLogs::Id: |
| Clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::DoorLock::Id: |
| Clusters::DoorLock::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::EthernetNetworkDiagnostics::Id: |
| Clusters::EthernetNetworkDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::GeneralCommissioning::Id: |
| Clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::Groups::Id: |
| Clusters::Groups::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::IasZone::Id: |
| Clusters::IasZone::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::Identify::Id: |
| Clusters::Identify::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::LevelControl::Id: |
| Clusters::LevelControl::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::LowPower::Id: |
| Clusters::LowPower::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::NetworkCommissioning::Id: |
| Clusters::NetworkCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::OtaSoftwareUpdateProvider::Id: |
| Clusters::OtaSoftwareUpdateProvider::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::OnOff::Id: |
| Clusters::OnOff::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::OperationalCredentials::Id: |
| Clusters::OperationalCredentials::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::Scenes::Id: |
| Clusters::Scenes::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::SoftwareDiagnostics::Id: |
| Clusters::SoftwareDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::TestCluster::Id: |
| Clusters::TestCluster::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::ThreadNetworkDiagnostics::Id: |
| Clusters::ThreadNetworkDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::WiFiNetworkDiagnostics::Id: |
| Clusters::WiFiNetworkDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::WindowCovering::Id: |
| Clusters::WindowCovering::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| default: |
| ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandPath.mClusterId)); |
| apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kNotFound, |
| Protocols::InteractionModel::Id, Protocols::InteractionModel::Status::UnsupportedCluster); |
| break; |
| } |
| |
| exit: |
| aReader.ExitContainer(dataTlvType); |
| Compatibility::ResetEmberAfObjects(); |
| } |
| |
| void DispatchSingleClusterResponseCommand(const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aReader, |
| CommandSender * apCommandObj) |
| { |
| ChipLogDetail(Zcl, "Received Cluster Command: Endpoint=%" PRIx16 " Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI, |
| aCommandPath.mEndpointId, ChipLogValueMEI(aCommandPath.mClusterId), ChipLogValueMEI(aCommandPath.mCommandId)); |
| |
| Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); |
| |
| TLV::TLVType dataTlvType; |
| SuccessOrExit(aReader.EnterContainer(dataTlvType)); |
| switch (aCommandPath.mClusterId) |
| { |
| default: |
| ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandPath.mClusterId)); |
| apCommandObj->AddStatusCode(aCommandPath, Protocols::SecureChannel::GeneralStatusCode::kNotFound, |
| Protocols::InteractionModel::Id, Protocols::InteractionModel::Status::UnsupportedCluster); |
| break; |
| } |
| |
| exit: |
| aReader.ExitContainer(dataTlvType); |
| Compatibility::ResetEmberAfObjects(); |
| } |
| |
| } // namespace app |
| } // namespace chip |