| /* |
| * |
| * Copyright (c) 2021 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // THIS FILE IS GENERATED BY ZAP |
| |
| #include <cinttypes> |
| #include <cstdint> |
| |
| #include "app/util/util.h" |
| #include <app-common/zap-generated/af-structs.h> |
| #include <app-common/zap-generated/callback.h> |
| #include <app-common/zap-generated/cluster-objects.h> |
| #include <app-common/zap-generated/ids/Clusters.h> |
| #include <app-common/zap-generated/ids/Commands.h> |
| #include <app/InteractionModelEngine.h> |
| #include <lib/core/CHIPSafeCasts.h> |
| #include <lib/support/TypeTraits.h> |
| |
| // Currently we need some work to keep compatible with ember lib. |
| #include <app/util/ember-compatibility-functions.h> |
| |
| namespace chip { |
| namespace app { |
| |
| namespace { |
| void ReportCommandUnsupported(Command * aCommandObj, const ConcreteCommandPath & aCommandPath) |
| { |
| aCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); |
| ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, |
| ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); |
| } |
| } // anonymous namespace |
| |
| // Cluster specific command parsing |
| |
| namespace Clusters { |
| |
| namespace AccountLogin { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::GetSetupPIN::Id: { |
| Commands::GetSetupPIN::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfAccountLoginClusterGetSetupPINCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::Login::Id: { |
| Commands::Login::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfAccountLoginClusterLoginCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace AccountLogin |
| |
| namespace AdministratorCommissioning { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::OpenBasicCommissioningWindow::Id: { |
| Commands::OpenBasicCommissioningWindow::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( |
| apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::OpenCommissioningWindow::Id: { |
| Commands::OpenCommissioningWindow::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(apCommandObj, aCommandPath, |
| commandData); |
| } |
| break; |
| } |
| case Commands::RevokeCommissioning::Id: { |
| Commands::RevokeCommissioning::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = |
| emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace AdministratorCommissioning |
| |
| namespace ApplicationBasic { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::ChangeStatus::Id: { |
| Commands::ChangeStatus::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfApplicationBasicClusterChangeStatusCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace ApplicationBasic |
| |
| namespace ApplicationLauncher { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::LaunchApp::Id: { |
| Commands::LaunchApp::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfApplicationLauncherClusterLaunchAppCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace ApplicationLauncher |
| |
| namespace AudioOutput { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::RenameOutput::Id: { |
| Commands::RenameOutput::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfAudioOutputClusterRenameOutputCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::SelectOutput::Id: { |
| Commands::SelectOutput::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfAudioOutputClusterSelectOutputCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace AudioOutput |
| |
| namespace Basic { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| } |
| |
| } // namespace Basic |
| |
| namespace Binding { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::Bind::Id: { |
| Commands::Bind::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfBindingClusterBindCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::Unbind::Id: { |
| Commands::Unbind::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfBindingClusterUnbindCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace Binding |
| |
| namespace ContentLauncher { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::LaunchContent::Id: { |
| Commands::LaunchContent::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfContentLauncherClusterLaunchContentCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::LaunchURL::Id: { |
| Commands::LaunchURL::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfContentLauncherClusterLaunchURLCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace ContentLauncher |
| |
| namespace DiagnosticLogs { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::RetrieveLogsRequest::Id: { |
| Commands::RetrieveLogsRequest::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace DiagnosticLogs |
| |
| namespace GeneralCommissioning { |
| |
| void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::ArmFailSafeResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(aCommandPath.mEndpointId, apCommandObj, |
| errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::CommissioningCompleteResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback( |
| aCommandPath.mEndpointId, apCommandObj, errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::SetRegulatoryConfigResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback( |
| aCommandPath.mEndpointId, apCommandObj, errorCode, debugText); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT |
| ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, |
| validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); |
| // A command with no arguments would never write currentDecodeTagId. If |
| // progress logging is also disabled, it would look unused. Silence that |
| // warning. |
| UNUSED_VAR(currentDecodeTagId); |
| } |
| } |
| |
| } // namespace GeneralCommissioning |
| |
| namespace GeneralCommissioning { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::ArmFailSafe::Id: { |
| Commands::ArmFailSafe::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::CommissioningComplete::Id: { |
| Commands::CommissioningComplete::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = |
| emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::SetRegulatoryConfig::Id: { |
| Commands::SetRegulatoryConfig::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace GeneralCommissioning |
| |
| namespace KeypadInput { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::SendKey::Id: { |
| Commands::SendKey::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfKeypadInputClusterSendKeyCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace KeypadInput |
| |
| namespace LevelControl { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::Move::Id: { |
| Commands::Move::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MoveToLevel::Id: { |
| Commands::MoveToLevel::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MoveToLevelWithOnOff::Id: { |
| Commands::MoveToLevelWithOnOff::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MoveWithOnOff::Id: { |
| Commands::MoveWithOnOff::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::Step::Id: { |
| Commands::Step::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::StepWithOnOff::Id: { |
| Commands::StepWithOnOff::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::Stop::Id: { |
| Commands::Stop::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::StopWithOnOff::Id: { |
| Commands::StopWithOnOff::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace LevelControl |
| |
| namespace LowPower { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::Sleep::Id: { |
| Commands::Sleep::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfLowPowerClusterSleepCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace LowPower |
| |
| namespace MediaInput { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::HideInputStatus::Id: { |
| Commands::HideInputStatus::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaInputClusterHideInputStatusCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::RenameInput::Id: { |
| Commands::RenameInput::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaInputClusterRenameInputCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::SelectInput::Id: { |
| Commands::SelectInput::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaInputClusterSelectInputCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::ShowInputStatus::Id: { |
| Commands::ShowInputStatus::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaInputClusterShowInputStatusCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace MediaInput |
| |
| namespace MediaPlayback { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::MediaFastForward::Id: { |
| Commands::MediaFastForward::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaFastForwardCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaNext::Id: { |
| Commands::MediaNext::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaNextCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaPause::Id: { |
| Commands::MediaPause::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaPauseCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaPlay::Id: { |
| Commands::MediaPlay::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaPlayCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaPrevious::Id: { |
| Commands::MediaPrevious::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaPreviousCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaRewind::Id: { |
| Commands::MediaRewind::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaRewindCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaSeek::Id: { |
| Commands::MediaSeek::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaSeekCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaSkipBackward::Id: { |
| Commands::MediaSkipBackward::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaSkipForward::Id: { |
| Commands::MediaSkipForward::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaStartOver::Id: { |
| Commands::MediaStartOver::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaStartOverCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::MediaStop::Id: { |
| Commands::MediaStop::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfMediaPlaybackClusterMediaStopCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace MediaPlayback |
| |
| namespace NetworkCommissioning { |
| |
| void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::AddThreadNetworkResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(aCommandPath.mEndpointId, |
| apCommandObj, errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::AddWiFiNetworkResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(aCommandPath.mEndpointId, |
| apCommandObj, errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::DisableNetworkResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(aCommandPath.mEndpointId, |
| apCommandObj, errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::EnableNetworkResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(aCommandPath.mEndpointId, apCommandObj, |
| errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::RemoveNetworkResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(aCommandPath.mEndpointId, apCommandObj, |
| errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::ScanNetworksResponse::Id: { |
| expectArgumentCount = 4; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; |
| /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; |
| bool argExists[4]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 4) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| case 2: |
| // Just for compatibility, we will add array type support in IM later. |
| TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(wifiScanResults)); |
| break; |
| case 3: |
| // Just for compatibility, we will add array type support in IM later. |
| TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(threadScanResults)); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback( |
| aCommandPath.mEndpointId, apCommandObj, errorCode, debugText, wifiScanResults, threadScanResults); |
| } |
| break; |
| } |
| case Commands::UpdateThreadNetworkResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback( |
| aCommandPath.mEndpointId, apCommandObj, errorCode, debugText); |
| } |
| break; |
| } |
| case Commands::UpdateWiFiNetworkResponse::Id: { |
| expectArgumentCount = 2; |
| uint8_t errorCode; |
| chip::CharSpan debugText; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(errorCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(debugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback( |
| aCommandPath.mEndpointId, apCommandObj, errorCode, debugText); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT |
| ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, |
| validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); |
| // A command with no arguments would never write currentDecodeTagId. If |
| // progress logging is also disabled, it would look unused. Silence that |
| // warning. |
| UNUSED_VAR(currentDecodeTagId); |
| } |
| } |
| |
| } // namespace NetworkCommissioning |
| |
| namespace NetworkCommissioning { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::AddThreadNetwork::Id: { |
| Commands::AddThreadNetwork::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::AddWiFiNetwork::Id: { |
| Commands::AddWiFiNetwork::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::DisableNetwork::Id: { |
| Commands::DisableNetwork::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::EnableNetwork::Id: { |
| Commands::EnableNetwork::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::RemoveNetwork::Id: { |
| Commands::RemoveNetwork::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::ScanNetworks::Id: { |
| Commands::ScanNetworks::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::UpdateThreadNetwork::Id: { |
| Commands::UpdateThreadNetwork::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::UpdateWiFiNetwork::Id: { |
| Commands::UpdateWiFiNetwork::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace NetworkCommissioning |
| |
| namespace OtaSoftwareUpdateProvider { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::ApplyUpdateRequest::Id: { |
| Commands::ApplyUpdateRequest::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = |
| emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::NotifyUpdateApplied::Id: { |
| Commands::NotifyUpdateApplied::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = |
| emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::QueryImage::Id: { |
| Commands::QueryImage::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace OtaSoftwareUpdateProvider |
| |
| namespace OnOff { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::Off::Id: { |
| Commands::Off::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::On::Id: { |
| Commands::On::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::Toggle::Id: { |
| Commands::Toggle::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace OnOff |
| |
| namespace OperationalCredentials { |
| |
| void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; |
| uint32_t validArgumentCount = 0; |
| uint32_t expectArgumentCount = 0; |
| uint32_t currentDecodeTagId = 0; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::AttestationResponse::Id: { |
| expectArgumentCount = 2; |
| chip::ByteSpan AttestationElements; |
| chip::ByteSpan Signature; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(AttestationElements); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(Signature); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterAttestationResponseCallback(aCommandPath.mEndpointId, apCommandObj, |
| AttestationElements, Signature); |
| } |
| break; |
| } |
| case Commands::CertificateChainResponse::Id: { |
| expectArgumentCount = 1; |
| chip::ByteSpan Certificate; |
| bool argExists[1]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 1) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(Certificate); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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 = emberAfOperationalCredentialsClusterCertificateChainResponseCallback(aCommandPath.mEndpointId, |
| apCommandObj, Certificate); |
| } |
| break; |
| } |
| case Commands::NOCResponse::Id: { |
| expectArgumentCount = 3; |
| uint8_t StatusCode; |
| uint8_t FabricIndex; |
| chip::CharSpan DebugText; |
| bool argExists[3]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 3) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(StatusCode); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(FabricIndex); |
| break; |
| case 2: |
| TLVUnpackError = aDataTlv.Get(DebugText); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. |
| TLVError = CHIP_NO_ERROR; |
| } |
| |
| if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterNOCResponseCallback(aCommandPath.mEndpointId, apCommandObj, |
| StatusCode, FabricIndex, DebugText); |
| } |
| break; |
| } |
| case Commands::OpCSRResponse::Id: { |
| expectArgumentCount = 2; |
| chip::ByteSpan NOCSRElements; |
| chip::ByteSpan AttestationSignature; |
| bool argExists[2]; |
| |
| memset(argExists, 0, sizeof argExists); |
| |
| while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) |
| { |
| // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. |
| // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. |
| if (!TLV::IsContextTag(aDataTlv.GetTag())) |
| { |
| continue; |
| } |
| currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); |
| if (currentDecodeTagId < 2) |
| { |
| if (argExists[currentDecodeTagId]) |
| { |
| ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); |
| TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; |
| break; |
| } |
| else |
| { |
| argExists[currentDecodeTagId] = true; |
| validArgumentCount++; |
| } |
| } |
| switch (currentDecodeTagId) |
| { |
| case 0: |
| TLVUnpackError = aDataTlv.Get(NOCSRElements); |
| break; |
| case 1: |
| TLVUnpackError = aDataTlv.Get(AttestationSignature); |
| break; |
| default: |
| // Unsupported tag, ignore it. |
| ChipLogProgress(Zcl, "Unknown TLV tag during processing."); |
| break; |
| } |
| if (CHIP_NO_ERROR != TLVUnpackError) |
| { |
| break; |
| } |
| } |
| |
| if (CHIP_END_OF_TLV == TLVError) |
| { |
| // CHIP_END_OF_TLV means we have iterated 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 = emberAfOperationalCredentialsClusterOpCSRResponseCallback(aCommandPath.mEndpointId, apCommandObj, |
| NOCSRElements, AttestationSignature); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, |
| "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT |
| ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, |
| validArgumentCount, expectArgumentCount, TLVError.Format(), TLVUnpackError.Format(), currentDecodeTagId); |
| // A command with no arguments would never write currentDecodeTagId. If |
| // progress logging is also disabled, it would look unused. Silence that |
| // warning. |
| UNUSED_VAR(currentDecodeTagId); |
| } |
| } |
| |
| } // namespace OperationalCredentials |
| |
| namespace OperationalCredentials { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::AddNOC::Id: { |
| Commands::AddNOC::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::AddTrustedRootCertificate::Id: { |
| Commands::AddTrustedRootCertificate::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = |
| emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::AttestationRequest::Id: { |
| Commands::AttestationRequest::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = |
| emberAfOperationalCredentialsClusterAttestationRequestCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::CertificateChainRequest::Id: { |
| Commands::CertificateChainRequest::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = |
| emberAfOperationalCredentialsClusterCertificateChainRequestCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::OpCSRRequest::Id: { |
| Commands::OpCSRRequest::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::RemoveFabric::Id: { |
| Commands::RemoveFabric::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::RemoveTrustedRootCertificate::Id: { |
| Commands::RemoveTrustedRootCertificate::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback(apCommandObj, aCommandPath, |
| commandData); |
| } |
| break; |
| } |
| case Commands::UpdateFabricLabel::Id: { |
| Commands::UpdateFabricLabel::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::UpdateNOC::Id: { |
| Commands::UpdateNOC::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace OperationalCredentials |
| |
| namespace TvChannel { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::ChangeChannel::Id: { |
| Commands::ChangeChannel::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfTvChannelClusterChangeChannelCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::ChangeChannelByNumber::Id: { |
| Commands::ChangeChannelByNumber::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfTvChannelClusterChangeChannelByNumberCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| case Commands::SkipChannel::Id: { |
| Commands::SkipChannel::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfTvChannelClusterSkipChannelCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace TvChannel |
| |
| namespace TargetNavigator { |
| |
| void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) |
| { |
| // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV |
| // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. |
| // Any error value TLVUnpackError means we have received an illegal value. |
| // The following variables are used for all commands to save code size. |
| CHIP_ERROR TLVError = CHIP_NO_ERROR; |
| bool wasHandled = false; |
| { |
| switch (aCommandPath.mCommandId) |
| { |
| case Commands::NavigateTarget::Id: { |
| Commands::NavigateTarget::DecodableType commandData; |
| TLVError = DataModel::Decode(aDataTlv, commandData); |
| if (TLVError == CHIP_NO_ERROR) |
| { |
| wasHandled = emberAfTargetNavigatorClusterNavigateTargetCallback(apCommandObj, aCommandPath, commandData); |
| } |
| break; |
| } |
| default: { |
| // Unrecognized command ID, error status will apply. |
| ReportCommandUnsupported(apCommandObj, aCommandPath); |
| return; |
| } |
| } |
| } |
| |
| if (CHIP_NO_ERROR != TLVError || !wasHandled) |
| { |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); |
| ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); |
| } |
| } |
| |
| } // namespace TargetNavigator |
| |
| } // namespace Clusters |
| |
| void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aReader, CommandHandler * apCommandObj) |
| { |
| Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); |
| |
| switch (aCommandPath.mClusterId) |
| { |
| case Clusters::AccountLogin::Id: |
| Clusters::AccountLogin::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::AdministratorCommissioning::Id: |
| Clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::ApplicationBasic::Id: |
| Clusters::ApplicationBasic::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::ApplicationLauncher::Id: |
| Clusters::ApplicationLauncher::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::AudioOutput::Id: |
| Clusters::AudioOutput::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::Basic::Id: |
| Clusters::Basic::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::Binding::Id: |
| Clusters::Binding::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::ContentLauncher::Id: |
| Clusters::ContentLauncher::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::DiagnosticLogs::Id: |
| Clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::GeneralCommissioning::Id: |
| Clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::KeypadInput::Id: |
| Clusters::KeypadInput::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::LevelControl::Id: |
| Clusters::LevelControl::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::LowPower::Id: |
| Clusters::LowPower::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::MediaInput::Id: |
| Clusters::MediaInput::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::MediaPlayback::Id: |
| Clusters::MediaPlayback::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::NetworkCommissioning::Id: |
| Clusters::NetworkCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::OtaSoftwareUpdateProvider::Id: |
| Clusters::OtaSoftwareUpdateProvider::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::OnOff::Id: |
| Clusters::OnOff::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::OperationalCredentials::Id: |
| Clusters::OperationalCredentials::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::TvChannel::Id: |
| Clusters::TvChannel::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::TargetNavigator::Id: |
| Clusters::TargetNavigator::DispatchServerCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| default: |
| ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandPath.mClusterId)); |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCluster); |
| break; |
| } |
| |
| Compatibility::ResetEmberAfObjects(); |
| } |
| |
| void DispatchSingleClusterResponseCommand(const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aReader, |
| CommandSender * apCommandObj) |
| { |
| Compatibility::SetupEmberAfObjects(apCommandObj, aCommandPath); |
| |
| TLV::TLVType dataTlvType; |
| SuccessOrExit(aReader.EnterContainer(dataTlvType)); |
| switch (aCommandPath.mClusterId) |
| { |
| case Clusters::GeneralCommissioning::Id: |
| Clusters::GeneralCommissioning::DispatchClientCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::NetworkCommissioning::Id: |
| Clusters::NetworkCommissioning::DispatchClientCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| case Clusters::OperationalCredentials::Id: |
| Clusters::OperationalCredentials::DispatchClientCommand(apCommandObj, aCommandPath, aReader); |
| break; |
| default: |
| ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandPath.mClusterId)); |
| apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCluster); |
| break; |
| } |
| |
| exit: |
| aReader.ExitContainer(dataTlvType); |
| Compatibility::ResetEmberAfObjects(); |
| } |
| |
| } // namespace app |
| } // namespace chip |