diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 676197be9ab2f2..88aae59da51a56 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -171,22 +171,6 @@ CHIP_ERROR ReadClusterDataVersion(const ConcreteClusterPath & aConcreteClusterPa return CHIP_NO_ERROR; } -CHIP_ERROR SendSuccessStatus(AttributeReportIB::Builder & aAttributeReport, AttributeDataIB::Builder & aAttributeDataIBBuilder) -{ - ReturnErrorOnFailure(aAttributeDataIBBuilder.EndOfAttributeDataIB()); - return aAttributeReport.EndOfAttributeReportIB(); -} - -CHIP_ERROR SendFailureStatus(const ConcreteAttributePath & aPath, AttributeReportIBs::Builder & aAttributeReports, - Protocols::InteractionModel::Status aStatus, TLV::TLVWriter * aReportCheckpoint) -{ - if (aReportCheckpoint != nullptr) - { - aAttributeReports.Rollback(*aReportCheckpoint); - } - return aAttributeReports.EncodeAttributeStatus(aPath, StatusIB(aStatus)); -} - // Helper function for trying to read an attribute value via an // AttributeAccessInterface. On failure, the read has failed. On success, the // aTriedEncode outparam is set to whether the AttributeAccessInterface tried to encode a value. @@ -302,7 +286,7 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b if (attributeCluster == nullptr && attributeMetadata == nullptr) { - return SendFailureStatus(aPath, aAttributeReports, UnsupportedAttributeStatus(aPath), nullptr); + return CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(UnsupportedAttributeStatus(aPath)); } // Check access control. A failed check will disallow the operation, and may or may not generate an attribute report @@ -319,8 +303,7 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b { return CHIP_NO_ERROR; } - - return SendFailureStatus(aPath, aAttributeReports, Protocols::InteractionModel::Status::UnsupportedAccess, nullptr); + return CHIP_IM_GLOBAL_STATUS(UnsupportedAccess); } } @@ -340,10 +323,6 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b } // Read attribute using Ember, if it doesn't have an override. - - TLV::TLVWriter backup; - aAttributeReports.Checkpoint(backup); - AttributeReportIB::Builder & attributeReport = aAttributeReports.CreateAttributeReport(); ReturnErrorOnFailure(aAttributeReports.GetError()); @@ -372,214 +351,174 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b static_cast(gEmberAttributeIOBufferSpan.size()), /* write = */ false); - if (status == Status::Success) + if (status != Status::Success) + { + return CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(status); + } + + TLV::TLVWriter * writer = attributeDataIBBuilder.GetWriter(); + VerifyOrReturnError(writer != nullptr, CHIP_NO_ERROR); + + const EmberAfAttributeType attributeType = attributeMetadata->attributeType; + const bool isNullable = attributeMetadata->IsNullable(); + const TLV::Tag tag = TLV::ContextTag(AttributeDataIB::Tag::kData); + + switch (AttributeBaseType(attributeType)) { - EmberAfAttributeType attributeType = attributeMetadata->attributeType; - bool isNullable = attributeMetadata->IsNullable(); - TLV::TLVWriter * writer = attributeDataIBBuilder.GetWriter(); - VerifyOrReturnError(writer != nullptr, CHIP_NO_ERROR); - TLV::Tag tag = TLV::ContextTag(AttributeDataIB::Tag::kData); - switch (AttributeBaseType(attributeType)) + case ZCL_NO_DATA_ATTRIBUTE_TYPE: // No data + ReturnErrorOnFailure(writer->PutNull(tag)); + break; + case ZCL_BOOLEAN_ATTRIBUTE_TYPE: // Boolean + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT8U_ATTRIBUTE_TYPE: // Unsigned 8-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT24U_ATTRIBUTE_TYPE: // Unsigned 24-bit integer + { + using IntType = OddSizedInteger<3, false>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT40U_ATTRIBUTE_TYPE: // Unsigned 40-bit integer + { + using IntType = OddSizedInteger<5, false>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT48U_ATTRIBUTE_TYPE: // Unsigned 48-bit integer + { + using IntType = OddSizedInteger<6, false>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT56U_ATTRIBUTE_TYPE: // Unsigned 56-bit integer + { + using IntType = OddSizedInteger<7, false>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT64U_ATTRIBUTE_TYPE: // Unsigned 64-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT8S_ATTRIBUTE_TYPE: // Signed 8-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT24S_ATTRIBUTE_TYPE: // Signed 24-bit integer + { + using IntType = OddSizedInteger<3, true>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_INT40S_ATTRIBUTE_TYPE: // Signed 40-bit integer + { + using IntType = OddSizedInteger<5, true>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT48S_ATTRIBUTE_TYPE: // Signed 48-bit integer + { + using IntType = OddSizedInteger<6, true>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT56S_ATTRIBUTE_TYPE: // Signed 56-bit integer + { + using IntType = OddSizedInteger<7, true>; + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + } + case ZCL_INT64S_ATTRIBUTE_TYPE: // Signed 64-bit integer + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_SINGLE_ATTRIBUTE_TYPE: // 32-bit float + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_DOUBLE_ATTRIBUTE_TYPE: // 64-bit float + ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); + break; + case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: // Char string + { + char * actualData = reinterpret_cast(gEmberAttributeIOBufferSpan.data() + 1); + uint8_t dataLength = gEmberAttributeIOBufferSpan[0]; + if (dataLength == 0xFF) { - case ZCL_NO_DATA_ATTRIBUTE_TYPE: // No data + VerifyOrReturnError(isNullable, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(writer->PutNull(tag)); - break; - case ZCL_BOOLEAN_ATTRIBUTE_TYPE: // Boolean - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - case ZCL_INT8U_ATTRIBUTE_TYPE: // Unsigned 8-bit integer - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer - { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT24U_ATTRIBUTE_TYPE: // Unsigned 24-bit integer - { - using IntType = OddSizedInteger<3, false>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer - { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; } - case ZCL_INT40U_ATTRIBUTE_TYPE: // Unsigned 40-bit integer + else { - using IntType = OddSizedInteger<5, false>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; + ReturnErrorOnFailure(writer->PutString(tag, actualData, dataLength)); } - case ZCL_INT48U_ATTRIBUTE_TYPE: // Unsigned 48-bit integer - { - using IntType = OddSizedInteger<6, false>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT56U_ATTRIBUTE_TYPE: // Unsigned 56-bit integer - { - using IntType = OddSizedInteger<7, false>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT64U_ATTRIBUTE_TYPE: // Unsigned 64-bit integer - { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT8S_ATTRIBUTE_TYPE: // Signed 8-bit integer - { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer - { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT24S_ATTRIBUTE_TYPE: // Signed 24-bit integer - { - using IntType = OddSizedInteger<3, true>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer - { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT40S_ATTRIBUTE_TYPE: // Signed 40-bit integer - { - using IntType = OddSizedInteger<5, true>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT48S_ATTRIBUTE_TYPE: // Signed 48-bit integer - { - using IntType = OddSizedInteger<6, true>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; - } - case ZCL_INT56S_ATTRIBUTE_TYPE: // Signed 56-bit integer + break; + } + case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: { + char * actualData = + reinterpret_cast(gEmberAttributeIOBufferSpan.data() + 2); // The pascal string contains 2 bytes length + uint16_t dataLength; + memcpy(&dataLength, gEmberAttributeIOBufferSpan.data(), sizeof(dataLength)); + if (dataLength == 0xFFFF) { - using IntType = OddSizedInteger<7, true>; - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; + VerifyOrReturnError(isNullable, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(writer->PutNull(tag)); } - case ZCL_INT64S_ATTRIBUTE_TYPE: // Signed 64-bit integer + else { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; + ReturnErrorOnFailure(writer->PutString(tag, actualData, dataLength)); } - case ZCL_SINGLE_ATTRIBUTE_TYPE: // 32-bit float + break; + } + case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: // Octet string + { + uint8_t * actualData = gEmberAttributeIOBufferSpan.data() + 1; + uint8_t dataLength = gEmberAttributeIOBufferSpan[0]; + if (dataLength == 0xFF) { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; + VerifyOrReturnError(isNullable, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(writer->PutNull(tag)); } - case ZCL_DOUBLE_ATTRIBUTE_TYPE: // 64-bit float + else { - ReturnErrorOnFailure(attributeBufferToNumericTlvData(*writer, isNullable)); - break; + ReturnErrorOnFailure(writer->Put(tag, chip::ByteSpan(actualData, dataLength))); } - case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: // Char string + break; + } + case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: { + uint8_t * actualData = gEmberAttributeIOBufferSpan.data() + 2; // The pascal string contains 2 bytes length + uint16_t dataLength; + memcpy(&dataLength, gEmberAttributeIOBufferSpan.data(), sizeof(dataLength)); + if (dataLength == 0xFFFF) { - char * actualData = reinterpret_cast(gEmberAttributeIOBufferSpan.data() + 1); - uint8_t dataLength = gEmberAttributeIOBufferSpan[0]; - if (dataLength == 0xFF) - { - if (isNullable) - { - ReturnErrorOnFailure(writer->PutNull(tag)); - } - else - { - return CHIP_ERROR_INCORRECT_STATE; - } - } - else - { - ReturnErrorOnFailure(writer->PutString(tag, actualData, dataLength)); - } - break; - } - case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: { - char * actualData = - reinterpret_cast(gEmberAttributeIOBufferSpan.data() + 2); // The pascal string contains 2 bytes length - uint16_t dataLength; - memcpy(&dataLength, gEmberAttributeIOBufferSpan.data(), sizeof(dataLength)); - if (dataLength == 0xFFFF) - { - if (isNullable) - { - ReturnErrorOnFailure(writer->PutNull(tag)); - } - else - { - return CHIP_ERROR_INCORRECT_STATE; - } - } - else - { - ReturnErrorOnFailure(writer->PutString(tag, actualData, dataLength)); - } - break; + VerifyOrReturnError(isNullable, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(writer->PutNull(tag)); } - case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: // Octet string + else { - uint8_t * actualData = gEmberAttributeIOBufferSpan.data() + 1; - uint8_t dataLength = gEmberAttributeIOBufferSpan[0]; - if (dataLength == 0xFF) - { - if (isNullable) - { - ReturnErrorOnFailure(writer->PutNull(tag)); - } - else - { - return CHIP_ERROR_INCORRECT_STATE; - } - } - else - { - ReturnErrorOnFailure(writer->Put(tag, chip::ByteSpan(actualData, dataLength))); - } - break; - } - case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: { - uint8_t * actualData = gEmberAttributeIOBufferSpan.data() + 2; // The pascal string contains 2 bytes length - uint16_t dataLength; - memcpy(&dataLength, gEmberAttributeIOBufferSpan.data(), sizeof(dataLength)); - if (dataLength == 0xFFFF) - { - if (isNullable) - { - ReturnErrorOnFailure(writer->PutNull(tag)); - } - else - { - return CHIP_ERROR_INCORRECT_STATE; - } - } - else - { - ReturnErrorOnFailure(writer->Put(tag, chip::ByteSpan(actualData, dataLength))); - } - break; - } - default: - ChipLogError(DataManagement, "Attribute type 0x%x not handled", static_cast(attributeType)); - status = Status::Failure; + ReturnErrorOnFailure(writer->Put(tag, chip::ByteSpan(actualData, dataLength))); } + break; } - - if (status == Protocols::InteractionModel::Status::Success) - { - return SendSuccessStatus(attributeReport, attributeDataIBBuilder); + default: + ChipLogError(DataManagement, "Attribute type 0x%x not handled", static_cast(attributeType)); + return CHIP_IM_GLOBAL_STATUS(Failure); } - return SendFailureStatus(aPath, aAttributeReports, status, &backup); + // If we got this far, placing the data to be read in the output TLVWriter succeeded. + // Try to terminate our attribute report to signal success. + ReturnErrorOnFailure(attributeDataIBBuilder.EndOfAttributeDataIB()); + return attributeReport.EndOfAttributeReportIB(); } namespace {