blob: 1f4c7d6f8c50cdae606d00f3824b933073c5d3cd [file] [log] [blame]
{{> header}}
#include <app-common/zap-generated/cluster-objects.h>
namespace chip {
namespace app {
namespace Clusters {
namespace detail {
CHIP_ERROR FlightCheckDecodeAndEnterStruct(TLV::TLVReader & reader, TLV::TLVType & outer)
{
TLV::TLVReader temp_reader;
// Make a copy of the struct reader to do pre-checks.
temp_reader.Init(reader);
// Ensure we have a single struct and that it's properly bounded.
CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrReturnError(TLV::kTLVType_Structure == temp_reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
ReturnErrorOnFailure(temp_reader.EnterContainer(outer));
while ((err = temp_reader.Next()) == CHIP_NO_ERROR)
{
if (!TLV::IsContextTag(temp_reader.GetTag()))
{
continue;
}
}
VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
ReturnErrorOnFailure(temp_reader.ExitContainer(outer));
// Guaranteed to work due to prior checks.
VerifyOrDie(reader.EnterContainer(outer) == CHIP_NO_ERROR);
return CHIP_NO_ERROR;
}
void ExitStructAfterDecode(TLV::TLVReader & reader, TLV::TLVType & outer)
{
// Ensure we exit the container. Will be OK since FlightCheckDecodeAndEnterStruct will have
// already been called, and generated code properly iterates over entire container.
VerifyOrDie(reader.Next() == CHIP_END_OF_TLV);
VerifyOrDie(reader.ExitContainer(outer) == CHIP_NO_ERROR);
}
// Structs shared across multiple clusters.
namespace Structs {
{{#zcl_structs}}
{{#if has_more_than_one_cluster}}
{{> cluster_objects_struct header=false}}
{{/if}}
{{/zcl_structs}}
} // namespace Structs
} // namespace detail
{{#zcl_clusters}}
namespace {{asUpperCamelCase name}} {
{{#zcl_structs}}
{{#first}}
namespace Structs {
{{/first}}
{{#unless has_more_than_one_cluster}}
{{> cluster_objects_struct header=false}}
{{/unless}}
{{#last}}
} // namespace Structs
{{/last}}
{{/zcl_structs}}
namespace Commands {
{{#zcl_commands}}
namespace {{asUpperCamelCase name}} {
CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const{
TLV::TLVType outer;
ReturnErrorOnFailure(aWriter.StartContainer(aTag, TLV::kTLVType_Structure, outer));
{{#zcl_command_arguments}}
ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::k{{asUpperCamelCase label}}), {{asLowerCamelCase label}}));
{{/zcl_command_arguments}}
ReturnErrorOnFailure(aWriter.EndContainer(outer));
return CHIP_NO_ERROR;
}
CHIP_ERROR DecodableType::Decode(TLV::TLVReader &reader) {
TLV::TLVType outer;
ReturnErrorOnFailure(chip::app::Clusters::detail::FlightCheckDecodeAndEnterStruct(reader, outer));
CHIP_ERROR err = CHIP_NO_ERROR;
while ((err = reader.Next()) == CHIP_NO_ERROR) {
if (!TLV::IsContextTag(reader.GetTag()))
{
continue;
}
switch (TLV::TagNumFromTag(reader.GetTag()))
{
{{#zcl_command_arguments}}
case to_underlying(Fields::k{{asUpperCamelCase label}}):
ReturnErrorOnFailure(DataModel::Decode(reader, {{asLowerCamelCase label}}));
break;
{{/zcl_command_arguments}}
default:
break;
}
}
chip::app::Clusters::detail::ExitStructAfterDecode(reader, outer);
return CHIP_NO_ERROR;
}
} // namespace {{asUpperCamelCase name}}.
{{/zcl_commands}}
} // namespace Commands
namespace Attributes {
CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader &reader, const ConcreteAttributePath &path) {
switch (path.mAttributeId)
{
{{#zcl_attributes_server}}
case Attributes::{{asUpperCamelCase label}}::TypeInfo::GetAttributeId():
ReturnErrorOnFailure(DataModel::Decode(reader, {{asLowerCamelCase label}}));
break;
{{/zcl_attributes_server}}
default:
break;
}
return CHIP_NO_ERROR;
}
} // namespace Attributes
namespace Events {
{{#zcl_events}}
namespace {{asUpperCamelCase name}} {
CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const{
TLV::TLVType outer;
ReturnErrorOnFailure(aWriter.StartContainer(aTag, TLV::kTLVType_Structure, outer));
{{#zcl_event_fields}}
{{#if_is_fabric_scoped_struct type}}
ReturnErrorOnFailure(DataModel::EncodeForRead(aWriter, TLV::ContextTag(Fields::k{{asUpperCamelCase name}}), GetFabricIndex(), {{asLowerCamelCase name}}));
{{else}}
ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::k{{asUpperCamelCase name}}), {{asLowerCamelCase name}}));
{{/if_is_fabric_scoped_struct}}
{{/zcl_event_fields}}
ReturnErrorOnFailure(aWriter.EndContainer(outer));
return CHIP_NO_ERROR;
}
CHIP_ERROR DecodableType::Decode(TLV::TLVReader &reader) {
TLV::TLVType outer;
ReturnErrorOnFailure(chip::app::Clusters::detail::FlightCheckDecodeAndEnterStruct(reader, outer));
CHIP_ERROR err = CHIP_NO_ERROR;
while ((err = reader.Next()) == CHIP_NO_ERROR) {
if (!TLV::IsContextTag(reader.GetTag()))
{
continue;
}
switch (TLV::TagNumFromTag(reader.GetTag()))
{
{{#zcl_event_fields}}
case to_underlying(Fields::k{{asUpperCamelCase name}}):
ReturnErrorOnFailure(DataModel::Decode(reader, {{asLowerCamelCase name}}));
break;
{{/zcl_event_fields}}
default:
break;
}
}
chip::app::Clusters::detail::ExitStructAfterDecode(reader, outer);
return CHIP_NO_ERROR;
}
} // namespace {{asUpperCamelCase name}}.
{{/zcl_events}}
} // namespace Events
} // namespace {{asUpperCamelCase name}}
{{/zcl_clusters}}
} // namespace Clusters
bool CommandNeedsTimedInvoke(ClusterId aCluster, CommandId aCommand)
{
// Maybe it would be smaller code to codegen a table and walk over it?
// Not sure.
switch (aCluster)
{
{{#zcl_clusters}}
{{#zcl_commands_that_need_timed_invoke}}
{{#first}}
case Clusters::{{asUpperCamelCase parent.name}}::Id:
{
switch (aCommand) {
{{/first}}
case Clusters::{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::Id:
{{#last}}
return true;
default:
return false;
}
}
{{/last}}
{{/zcl_commands_that_need_timed_invoke}}
{{/zcl_clusters}}
default:
break;
}
return false;
}
bool CommandIsFabricScoped(ClusterId aCluster, CommandId aCommand)
{
// Maybe it would be smaller code to codegen a table and walk over it?
// Not sure.
switch (aCluster)
{
{{#zcl_clusters}}
{{#zcl_commands}}
{{#first}}
case Clusters::{{asUpperCamelCase parent.name}}::Id:
{
switch (aCommand) {
{{/first}}
{{#if isFabricScoped}}
case Clusters::{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::Id:
return true;
{{/if}}
{{#last}}
default:
return false;
}
}
{{/last}}
{{/zcl_commands}}
{{/zcl_clusters}}
}
return false;
}
} // namespace app
} // namespace chip