| /* |
| * |
| * Copyright (c) 2021 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // THIS FILE IS GENERATED BY ZAP |
| |
| #include <cinttypes> |
| #include <cstdint> |
| |
| #include "app/common/gen/af-structs.h" |
| #include "app/common/gen/callback.h" |
| #include "app/common/gen/ids/Clusters.h" |
| #include "app/common/gen/ids/Commands.h" |
| #include "app/util/util.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, EndpointId aEndpointId, ClusterId aClusterId, CommandId aCommandId) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| aClusterId, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| aCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); |
| ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandId), |
| ChipLogValueMEI(aClusterId)); |
| } |
| } // anonymous namespace |
| |
| // Cluster specific command parsing |
| |
| namespace clusters { |
| |
| namespace AdministratorCommissioning { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { |
| 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(aEndpointId, apCommandObj, |
| CommissioningTimeout); |
| } |
| break; |
| } |
| case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { |
| 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( |
| aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); |
| } |
| break; |
| } |
| case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { |
| |
| wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::AdministratorCommissioning::Id, aCommandId, |
| (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::BarrierControl::Commands::Ids::BarrierControlGoToPercent: { |
| 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(aEndpointId, apCommandObj, percentOpen); |
| } |
| break; |
| } |
| case Clusters::BarrierControl::Commands::Ids::BarrierControlStop: { |
| |
| wasHandled = emberAfBarrierControlClusterBarrierControlStopCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::BarrierControl::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::BarrierControl::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::Basic::Id, aCommandId); |
| } |
| |
| } // namespace Basic |
| |
| namespace Binding { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::Binding::Commands::Ids::Bind: { |
| 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(aEndpointId, apCommandObj, nodeId, groupId, endpointId, clusterId); |
| } |
| break; |
| } |
| case Clusters::Binding::Commands::Ids::Unbind: { |
| 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(aEndpointId, apCommandObj, nodeId, groupId, endpointId, clusterId); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::Binding::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::Binding::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::ColorControl::Commands::Ids::MoveColor: { |
| 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(aEndpointId, apCommandObj, rateX, rateY, optionsMask, |
| optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveColorTemperature: { |
| 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( |
| aEndpointId, apCommandObj, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, |
| optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveHue: { |
| 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(aEndpointId, apCommandObj, moveMode, rate, optionsMask, |
| optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveSaturation: { |
| 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(aEndpointId, apCommandObj, moveMode, rate, |
| optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveToColor: { |
| 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(aEndpointId, apCommandObj, colorX, colorY, |
| transitionTime, optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveToColorTemperature: { |
| 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(aEndpointId, apCommandObj, colorTemperature, |
| transitionTime, optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveToHue: { |
| 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(aEndpointId, apCommandObj, hue, direction, transitionTime, |
| optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveToHueAndSaturation: { |
| 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(aEndpointId, apCommandObj, hue, saturation, |
| transitionTime, optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::MoveToSaturation: { |
| 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(aEndpointId, apCommandObj, saturation, |
| transitionTime, optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::StepColor: { |
| 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(aEndpointId, apCommandObj, stepX, stepY, transitionTime, |
| optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::StepColorTemperature: { |
| 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( |
| aEndpointId, apCommandObj, stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, |
| optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::StepHue: { |
| 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(aEndpointId, apCommandObj, stepMode, stepSize, |
| transitionTime, optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::StepSaturation: { |
| 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(aEndpointId, apCommandObj, stepMode, stepSize, |
| transitionTime, optionsMask, optionsOverride); |
| } |
| break; |
| } |
| case Clusters::ColorControl::Commands::Ids::StopMoveStep: { |
| 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(aEndpointId, apCommandObj, optionsMask, optionsOverride); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::ColorControl::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::ColorControl::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::DiagnosticLogs::Commands::Ids::RetrieveLogsRequest: { |
| 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(aEndpointId, apCommandObj, intent, |
| requestedProtocol, transferFileDesignator); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::DiagnosticLogs::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::DiagnosticLogs::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::DoorLock::Commands::Ids::ClearAllPins: { |
| |
| wasHandled = emberAfDoorLockClusterClearAllPinsCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::ClearAllRfids: { |
| |
| wasHandled = emberAfDoorLockClusterClearAllRfidsCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::ClearHolidaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::ClearPin: { |
| 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(aEndpointId, apCommandObj, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::ClearRfid: { |
| 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(aEndpointId, apCommandObj, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::ClearWeekdaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::ClearYeardaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::GetHolidaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::GetLogRecord: { |
| 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(aEndpointId, apCommandObj, logIndex); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::GetPin: { |
| 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(aEndpointId, apCommandObj, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::GetRfid: { |
| 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(aEndpointId, apCommandObj, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::GetUserType: { |
| 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(aEndpointId, apCommandObj, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::GetWeekdaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::GetYeardaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId, userId); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::LockDoor: { |
| expectArgumentCount = 1; |
| const uint8_t * 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: |
| // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. |
| TLVUnpackError = aDataTlv.GetDataPtr(PIN); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) |
| { |
| wasHandled = emberAfDoorLockClusterLockDoorCallback(aEndpointId, apCommandObj, const_cast<uint8_t *>(PIN)); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::SetHolidaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId, localStartTime, |
| localEndTime, operatingModeDuringHoliday); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::SetPin: { |
| expectArgumentCount = 4; |
| uint16_t userId; |
| uint8_t userStatus; |
| uint8_t userType; |
| const uint8_t * pin; |
| bool argExists[4]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 4) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(userId); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(userStatus); |
| break; |
| case 2: |
| TLVUnpackError = aDataTlv.Get(userType); |
| break; |
| case 3: |
| // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. |
| TLVUnpackError = aDataTlv.GetDataPtr(pin); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) |
| { |
| wasHandled = emberAfDoorLockClusterSetPinCallback(aEndpointId, apCommandObj, userId, userStatus, userType, |
| const_cast<uint8_t *>(pin)); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::SetRfid: { |
| expectArgumentCount = 4; |
| uint16_t userId; |
| uint8_t userStatus; |
| uint8_t userType; |
| const uint8_t * 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: |
| // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. |
| TLVUnpackError = aDataTlv.GetDataPtr(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(aEndpointId, apCommandObj, userId, userStatus, userType, |
| const_cast<uint8_t *>(id)); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::SetUserType: { |
| 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(aEndpointId, apCommandObj, userId, userType); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::SetWeekdaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId, userId, |
| daysMask, startHour, startMinute, endHour, endMinute); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::SetYeardaySchedule: { |
| 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(aEndpointId, apCommandObj, scheduleId, userId, |
| localStartTime, localEndTime); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::UnlockDoor: { |
| expectArgumentCount = 1; |
| const uint8_t * 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: |
| // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. |
| TLVUnpackError = aDataTlv.GetDataPtr(PIN); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) |
| { |
| wasHandled = emberAfDoorLockClusterUnlockDoorCallback(aEndpointId, apCommandObj, const_cast<uint8_t *>(PIN)); |
| } |
| break; |
| } |
| case Clusters::DoorLock::Commands::Ids::UnlockWithTimeout: { |
| expectArgumentCount = 2; |
| uint16_t timeoutInSeconds; |
| const uint8_t * 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: |
| // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. |
| TLVUnpackError = aDataTlv.GetDataPtr(pin); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfDoorLockClusterUnlockWithTimeoutCallback(aEndpointId, apCommandObj, timeoutInSeconds, |
| const_cast<uint8_t *>(pin)); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::DoorLock::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::DoorLock::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT |
| ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, |
| validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); |
| // A command with no arguments would never write currentDecodeTagId. If |
| // progress logging is also disabled, it would look unused. Silence that |
| // warning. |
| UNUSED_VAR(currentDecodeTagId); |
| } |
| } |
| |
| } // namespace DoorLock |
| |
| namespace GeneralCommissioning { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::GeneralCommissioning::Commands::Ids::ArmFailSafe: { |
| 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(aEndpointId, apCommandObj, expiryLengthSeconds, |
| breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| case Clusters::GeneralCommissioning::Commands::Ids::CommissioningComplete: { |
| |
| wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::GeneralCommissioning::Commands::Ids::SetRegulatoryConfig: { |
| 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( |
| aEndpointId, apCommandObj, location, const_cast<uint8_t *>(countryCode), breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::GeneralCommissioning::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::GeneralCommissioning::Id, aCommandId, |
| (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::Groups::Commands::Ids::AddGroup: { |
| 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(aEndpointId, apCommandObj, groupId, const_cast<uint8_t *>(groupName)); |
| } |
| break; |
| } |
| case Clusters::Groups::Commands::Ids::AddGroupIfIdentifying: { |
| 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(aEndpointId, apCommandObj, groupId, |
| const_cast<uint8_t *>(groupName)); |
| } |
| break; |
| } |
| case Clusters::Groups::Commands::Ids::GetGroupMembership: { |
| 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(aEndpointId, apCommandObj, groupCount, groupList); |
| } |
| break; |
| } |
| case Clusters::Groups::Commands::Ids::RemoveAllGroups: { |
| |
| wasHandled = emberAfGroupsClusterRemoveAllGroupsCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::Groups::Commands::Ids::RemoveGroup: { |
| 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(aEndpointId, apCommandObj, groupId); |
| } |
| break; |
| } |
| case Clusters::Groups::Commands::Ids::ViewGroup: { |
| 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(aEndpointId, apCommandObj, groupId); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::Groups::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::Groups::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::IasZone::Commands::Ids::ZoneEnrollResponse: { |
| 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(aEndpointId, apCommandObj, enrollResponseCode, zoneId); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::IasZone::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::IasZone::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::Identify::Commands::Ids::Identify: { |
| 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(aEndpointId, apCommandObj, identifyTime); |
| } |
| break; |
| } |
| case Clusters::Identify::Commands::Ids::IdentifyQuery: { |
| |
| wasHandled = emberAfIdentifyClusterIdentifyQueryCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::Identify::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::Identify::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::LevelControl::Commands::Ids::Move: { |
| 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(aEndpointId, apCommandObj, moveMode, rate, optionMask, optionOverride); |
| } |
| break; |
| } |
| case Clusters::LevelControl::Commands::Ids::MoveToLevel: { |
| 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(aEndpointId, apCommandObj, level, transitionTime, |
| optionMask, optionOverride); |
| } |
| break; |
| } |
| case Clusters::LevelControl::Commands::Ids::MoveToLevelWithOnOff: { |
| 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(aEndpointId, apCommandObj, level, transitionTime); |
| } |
| break; |
| } |
| case Clusters::LevelControl::Commands::Ids::MoveWithOnOff: { |
| 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(aEndpointId, apCommandObj, moveMode, rate); |
| } |
| break; |
| } |
| case Clusters::LevelControl::Commands::Ids::Step: { |
| 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(aEndpointId, apCommandObj, stepMode, stepSize, transitionTime, |
| optionMask, optionOverride); |
| } |
| break; |
| } |
| case Clusters::LevelControl::Commands::Ids::StepWithOnOff: { |
| 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(aEndpointId, apCommandObj, stepMode, stepSize, transitionTime); |
| } |
| break; |
| } |
| case Clusters::LevelControl::Commands::Ids::Stop: { |
| 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(aEndpointId, apCommandObj, optionMask, optionOverride); |
| } |
| break; |
| } |
| case Clusters::LevelControl::Commands::Ids::StopWithOnOff: { |
| |
| wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::LevelControl::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::LevelControl::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::LowPower::Commands::Ids::Sleep: { |
| |
| wasHandled = emberAfLowPowerClusterSleepCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::LowPower::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::LowPower::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::NetworkCommissioning::Commands::Ids::AddThreadNetwork: { |
| 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(aEndpointId, apCommandObj, |
| operationalDataset, breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::AddWiFiNetwork: { |
| 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(aEndpointId, apCommandObj, ssid, credentials, |
| breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::DisableNetwork: { |
| 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(aEndpointId, apCommandObj, networkID, |
| breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::EnableNetwork: { |
| 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(aEndpointId, apCommandObj, networkID, |
| breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::GetLastNetworkCommissioningResult: { |
| 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(aEndpointId, apCommandObj, |
| timeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::RemoveNetwork: { |
| 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(aEndpointId, apCommandObj, NetworkID, |
| Breadcrumb, TimeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::ScanNetworks: { |
| 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(aEndpointId, apCommandObj, ssid, breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::UpdateThreadNetwork: { |
| 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( |
| aEndpointId, apCommandObj, operationalDataset, breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| case Clusters::NetworkCommissioning::Commands::Ids::UpdateWiFiNetwork: { |
| 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(aEndpointId, apCommandObj, ssid, |
| credentials, breadcrumb, timeoutMs); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::NetworkCommissioning::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::NetworkCommissioning::Id, aCommandId, |
| (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::OtaSoftwareUpdateProvider::Commands::Ids::ApplyUpdateRequest: { |
| 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(aEndpointId, apCommandObj, |
| updateToken, newVersion); |
| } |
| break; |
| } |
| case Clusters::OtaSoftwareUpdateProvider::Commands::Ids::NotifyUpdateApplied: { |
| expectArgumentCount = 2; |
| chip::ByteSpan updateToken; |
| uint32_t currentVersion; |
| 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(currentVersion); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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(aEndpointId, apCommandObj, |
| updateToken, currentVersion); |
| } |
| break; |
| } |
| case Clusters::OtaSoftwareUpdateProvider::Commands::Ids::QueryImage: { |
| expectArgumentCount = 9; |
| uint16_t vendorId; |
| uint16_t productId; |
| uint16_t imageType; |
| uint16_t hardwareVersion; |
| uint32_t currentVersion; |
| uint8_t protocolsSupported; |
| const uint8_t * location; |
| bool requestorCanConsent; |
| chip::ByteSpan metadataForProvider; |
| bool argExists[9]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 9) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| 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(imageType); |
| break; |
| case 3: |
| TLVUnpackError = aDataTlv.Get(hardwareVersion); |
| break; |
| case 4: |
| TLVUnpackError = aDataTlv.Get(currentVersion); |
| break; |
| case 5: |
| TLVUnpackError = aDataTlv.Get(protocolsSupported); |
| break; |
| case 6: |
| // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. |
| TLVUnpackError = aDataTlv.GetDataPtr(location); |
| break; |
| case 7: |
| TLVUnpackError = aDataTlv.Get(requestorCanConsent); |
| break; |
| case 8: |
| 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 && 9 == validArgumentCount) |
| { |
| wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback( |
| aEndpointId, apCommandObj, vendorId, productId, imageType, hardwareVersion, currentVersion, protocolsSupported, |
| const_cast<uint8_t *>(location), requestorCanConsent, metadataForProvider); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::OtaSoftwareUpdateProvider::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::OtaSoftwareUpdateProvider::Id, aCommandId, |
| (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::OnOff::Commands::Ids::Off: { |
| |
| wasHandled = emberAfOnOffClusterOffCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::OnOff::Commands::Ids::On: { |
| |
| wasHandled = emberAfOnOffClusterOnCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::OnOff::Commands::Ids::Toggle: { |
| |
| wasHandled = emberAfOnOffClusterToggleCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::OnOff::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::OnOff::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::OperationalCredentials::Commands::Ids::AddNOC: { |
| expectArgumentCount = 4; |
| chip::ByteSpan NOCArray; |
| chip::ByteSpan IPKValue; |
| chip::NodeId CaseAdminNode; |
| uint16_t AdminVendorId; |
| 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(NOCArray); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(IPKValue); |
| break; |
| case 2: |
| TLVUnpackError = aDataTlv.Get(CaseAdminNode); |
| break; |
| case 3: |
| 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 && 4 == validArgumentCount) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback(aEndpointId, apCommandObj, NOCArray, IPKValue, |
| CaseAdminNode, AdminVendorId); |
| } |
| break; |
| } |
| case Clusters::OperationalCredentials::Commands::Ids::AddTrustedRootCertificate: { |
| 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(aEndpointId, apCommandObj, |
| RootCertificate); |
| } |
| break; |
| } |
| case Clusters::OperationalCredentials::Commands::Ids::OpCSRRequest: { |
| 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(aEndpointId, apCommandObj, CSRNonce); |
| } |
| break; |
| } |
| case Clusters::OperationalCredentials::Commands::Ids::RemoveFabric: { |
| 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(aEndpointId, apCommandObj, FabricIndex); |
| } |
| break; |
| } |
| case Clusters::OperationalCredentials::Commands::Ids::RemoveTrustedRootCertificate: { |
| 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(aEndpointId, apCommandObj, |
| TrustedRootIdentifier); |
| } |
| break; |
| } |
| case Clusters::OperationalCredentials::Commands::Ids::UpdateFabricLabel: { |
| 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(aEndpointId, apCommandObj, |
| const_cast<uint8_t *>(Label)); |
| } |
| break; |
| } |
| case Clusters::OperationalCredentials::Commands::Ids::UpdateNOC: { |
| expectArgumentCount = 1; |
| chip::ByteSpan NOCArray; |
| 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(NOCArray); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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 = emberAfOperationalCredentialsClusterUpdateNOCCallback(aEndpointId, apCommandObj, NOCArray); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::OperationalCredentials::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::OperationalCredentials::Id, aCommandId, |
| (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::Scenes::Commands::Ids::AddScene: { |
| 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(aEndpointId, apCommandObj, groupId, sceneId, transitionTime, |
| const_cast<uint8_t *>(sceneName), extensionFieldSets); |
| } |
| break; |
| } |
| case Clusters::Scenes::Commands::Ids::GetSceneMembership: { |
| 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(aEndpointId, apCommandObj, groupId); |
| } |
| break; |
| } |
| case Clusters::Scenes::Commands::Ids::RecallScene: { |
| 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(aEndpointId, apCommandObj, groupId, sceneId, transitionTime); |
| } |
| break; |
| } |
| case Clusters::Scenes::Commands::Ids::RemoveAllScenes: { |
| 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(aEndpointId, apCommandObj, groupId); |
| } |
| break; |
| } |
| case Clusters::Scenes::Commands::Ids::RemoveScene: { |
| 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(aEndpointId, apCommandObj, groupId, sceneId); |
| } |
| break; |
| } |
| case Clusters::Scenes::Commands::Ids::StoreScene: { |
| 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(aEndpointId, apCommandObj, groupId, sceneId); |
| } |
| break; |
| } |
| case Clusters::Scenes::Commands::Ids::ViewScene: { |
| 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(aEndpointId, apCommandObj, groupId, sceneId); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::Scenes::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::Scenes::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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 TestCluster { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandId) |
| { |
| case Clusters::TestCluster::Commands::Ids::Test: { |
| |
| wasHandled = emberAfTestClusterClusterTestCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::TestCluster::Commands::Ids::TestNotHandled: { |
| |
| wasHandled = emberAfTestClusterClusterTestNotHandledCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| case Clusters::TestCluster::Commands::Ids::TestSpecific: { |
| |
| wasHandled = emberAfTestClusterClusterTestSpecificCallback(aEndpointId, apCommandObj); |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::TestCluster::Id, aCommandId); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| CommandPathParams returnStatusParam = { aEndpointId, |
| 0, // GroupId |
| Clusters::TestCluster::Id, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" 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 clusters |
| |
| void DispatchSingleClusterCommand(ClusterId aClusterId, CommandId aCommandId, EndpointId aEndPointId, TLV::TLVReader & aReader, |
| CommandHandler * apCommandObj) |
| { |
| ChipLogDetail(Zcl, "Received Cluster Command: Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI " Endpoint=%" PRIx16, |
| ChipLogValueMEI(aClusterId), ChipLogValueMEI(aCommandId), aEndPointId); |
| Compatibility::SetupEmberAfObjects(apCommandObj, aClusterId, aCommandId, aEndPointId); |
| TLV::TLVType dataTlvType; |
| SuccessOrExit(aReader.EnterContainer(dataTlvType)); |
| switch (aClusterId) |
| { |
| case Clusters::AdministratorCommissioning::Id: |
| clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::BarrierControl::Id: |
| clusters::BarrierControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::Basic::Id: |
| clusters::Basic::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::Binding::Id: |
| clusters::Binding::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::ColorControl::Id: |
| clusters::ColorControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::DiagnosticLogs::Id: |
| clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::DoorLock::Id: |
| clusters::DoorLock::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::GeneralCommissioning::Id: |
| clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::Groups::Id: |
| clusters::Groups::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::IasZone::Id: |
| clusters::IasZone::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::Identify::Id: |
| clusters::Identify::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::LevelControl::Id: |
| clusters::LevelControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::LowPower::Id: |
| clusters::LowPower::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::NetworkCommissioning::Id: |
| clusters::NetworkCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::OtaSoftwareUpdateProvider::Id: |
| clusters::OtaSoftwareUpdateProvider::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::OnOff::Id: |
| clusters::OnOff::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::OperationalCredentials::Id: |
| clusters::OperationalCredentials::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::Scenes::Id: |
| clusters::Scenes::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| case Clusters::TestCluster::Id: |
| clusters::TestCluster::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); |
| break; |
| default: |
| // Unrecognized cluster ID, error status will apply. |
| CommandPathParams returnStatusParam = { aEndPointId, |
| 0, // GroupId |
| aClusterId, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogError(Zcl, "Unknown cluster %" PRIx32, aClusterId); |
| break; |
| } |
| exit: |
| Compatibility::ResetEmberAfObjects(); |
| aReader.ExitContainer(dataTlvType); |
| } |
| |
| void DispatchSingleClusterResponseCommand(ClusterId aClusterId, CommandId aCommandId, EndpointId aEndPointId, |
| TLV::TLVReader & aReader, CommandSender * apCommandObj) |
| { |
| ChipLogDetail(Zcl, "Received Cluster Command: Cluster=%" PRIx32 " Command=%" PRIx32 " Endpoint=%" PRIx16, aClusterId, |
| aCommandId, aEndPointId); |
| Compatibility::SetupEmberAfObjects(apCommandObj, aClusterId, aCommandId, aEndPointId); |
| TLV::TLVType dataTlvType; |
| SuccessOrExit(aReader.EnterContainer(dataTlvType)); |
| switch (aClusterId) |
| { |
| default: |
| // Unrecognized cluster ID, error status will apply. |
| CommandPathParams returnStatusParam = { aEndPointId, |
| 0, // GroupId |
| aClusterId, aCommandId, (CommandPathFlags::kEndpointIdValid) }; |
| apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, |
| Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); |
| ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aClusterId)); |
| break; |
| } |
| exit: |
| Compatibility::ResetEmberAfObjects(); |
| aReader.ExitContainer(dataTlvType); |
| } |
| |
| } // namespace app |
| } // namespace chip |