Skip to content

Commit

Permalink
Updated the PR to the changes in the attributeValue -> ValueUnsigned …
Browse files Browse the repository at this point in the history
…struct, needs to test all possibilities (WIP)
  • Loading branch information
lpbeliveau-silabs committed Aug 1, 2024
1 parent f7a7d34 commit 6c3dcad
Show file tree
Hide file tree
Showing 22 changed files with 358 additions and 268 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9410,3 +9410,5 @@ endpoint 65534 {
handle command ReorderNetwork;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -6995,3 +6995,5 @@ endpoint 65534 {
handle command ReorderNetwork;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -2982,3 +2982,5 @@ endpoint 2 {
ram attribute clusterRevision default = 1;
}
}


2 changes: 2 additions & 0 deletions examples/light-switch-app/qpg/zap/switch.matter
Original file line number Diff line number Diff line change
Expand Up @@ -3066,3 +3066,5 @@ endpoint 2 {
ram attribute clusterRevision default = 1;
}
}


2 changes: 2 additions & 0 deletions examples/lighting-app/lighting-common/lighting-app.matter
Original file line number Diff line number Diff line change
Expand Up @@ -2888,3 +2888,5 @@ endpoint 1 {
ram attribute clusterRevision default = 4;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -2463,3 +2463,5 @@ endpoint 1 {
handle command StepColorTemperature;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -2752,3 +2752,5 @@ endpoint 1 {
handle command StepColorTemperature;
}
}


2 changes: 2 additions & 0 deletions examples/placeholder/linux/apps/app1/config.matter
Original file line number Diff line number Diff line change
Expand Up @@ -9269,3 +9269,5 @@ endpoint 1 {
callback attribute clusterRevision default = 4;
}
}


2 changes: 2 additions & 0 deletions examples/placeholder/linux/apps/app2/config.matter
Original file line number Diff line number Diff line change
Expand Up @@ -9208,3 +9208,5 @@ endpoint 1 {
callback attribute clusterRevision default = 4;
}
}


2 changes: 2 additions & 0 deletions examples/thermostat/nxp/zap/thermostat_matter_thread.matter
Original file line number Diff line number Diff line change
Expand Up @@ -2698,3 +2698,5 @@ endpoint 1 {
handle command SetpointRaiseLower;
}
}


2 changes: 2 additions & 0 deletions examples/thermostat/nxp/zap/thermostat_matter_wifi.matter
Original file line number Diff line number Diff line change
Expand Up @@ -2551,3 +2551,5 @@ endpoint 1 {
handle command SetpointRaiseLower;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -3730,3 +3730,5 @@ endpoint 1 {
handle command MoveToColorTemperature;
}
}


115 changes: 74 additions & 41 deletions src/app/clusters/scenes-server/SceneHandlerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace {
template <int ByteSize, bool IsSigned>
using OddSizedInteger = app::OddSizedInteger<ByteSize, IsSigned>;
using ConcreteAttributePath = app::ConcreteAttributePath;
using AttributeValuePairType = app::Clusters::ScenesManagement::Structs::AttributeValuePair::Type;
using AttributeValuePairType = app::Clusters::ScenesManagement::Structs::AttributeValuePairStruct::Type;

/// ConvertDefaultValueToWorkingValue
/// @brief Helper function to convert a byte array to a value of the given type.
Expand All @@ -47,32 +47,61 @@ ConvertDefaultValueToWorkingValue(const EmberAfDefaultAttributeValue & defaultVa
return app::NumericAttributeTraits<Type>::StorageToWorking(sValue);
}

/// IsOnlyOneValuePopulated
/// @brief Helper function to verify if only one value is populated in a given AttributeValuePairType
/// @param AttributeValuePairType & type AttributeValuePairType to verify
/// @return bool true if only one value is populated, false otherwise
bool IsOnlyOneValuePopulated(const AttributeValuePairType & type)
{
int count = 0;
if (type.valueUnsigned8.HasValue())
count++;
if (type.valueSigned8.HasValue())
count++;
if (type.valueUnsigned16.HasValue())
count++;
if (type.valueSigned16.HasValue())
count++;
if (type.valueUnsigned32.HasValue())
count++;
if (type.valueSigned32.HasValue())
count++;
if (type.valueUnsigned64.HasValue())
count++;
if (type.valueSigned64.HasValue())
count++;
return count == 1;
}

/// CapAttributeID
/// Cap the attribute value based on the attribute's min and max if they are defined,
/// or based on the attribute's size if they are not.
/// @param[in] aVPair AttributeValuePairType
/// @param[in] metadata EmberAfAttributeMetadata
///
template <typename Type>
void CapAttributeID(AttributeValuePairType & aVPair, const EmberAfAttributeMetadata * metadata)
void CapAttributeID(typename app::NumericAttributeTraits<Type>::WorkingType & Value, const EmberAfAttributeMetadata * metadata)
{
using IntType = app::NumericAttributeTraits<Type>;
using WorkingType = typename IntType::WorkingType;

WorkingType maxValue;
WorkingType minValue;

// Check if the attribute type is signed
// Min/Max Value capps for the OddSize integers
if (metadata->IsSignedIntegerAttribute())
{
// We use emberAfAttributeSize for cases like INT24S, INT40S, INT48S, INT56S where numeric_limits<WorkingType>::max()
// wouldn't work
maxValue = static_cast<WorkingType>((1ULL << (emberAfAttributeSize(metadata) * 8 - 1)) - 1);
minValue = static_cast<WorkingType>(-(1ULL << (emberAfAttributeSize(metadata) * 8 - 1)));
}
else
{
// We use emberAfAttributeSize for cases like INT24U, INT40U, INT48U, INT56U where numeric_limits<WorkingType>::max()
// wouldn't work
maxValue = static_cast<WorkingType>((1ULL << (emberAfAttributeSize(metadata) * 8)) - 1);
minValue = static_cast<WorkingType>(0);
}

// Ensure that the metadata's signedness matches the working type's signedness
Expand All @@ -81,7 +110,7 @@ void CapAttributeID(AttributeValuePairType & aVPair, const EmberAfAttributeMetad
if (metadata->IsBoolean())
{
// Caping the value to 1 in case values greater than 1 are set
aVPair.attributeValue = aVPair.attributeValue ? 1 : 0;
Value = Value ? 1 : 0;
return;
}

Expand All @@ -93,36 +122,29 @@ void CapAttributeID(AttributeValuePairType & aVPair, const EmberAfAttributeMetad
WorkingType rangeMax = ConvertDefaultValueToWorkingValue<Type>(minMaxValue->maxValue);

// Cap based on minimum value
if (rangeMin > static_cast<WorkingType>(aVPair.attributeValue))
if (rangeMin > Value)
{
aVPair.attributeValue = static_cast<std::make_unsigned_t<WorkingType>>(rangeMin);
Value = rangeMin;
// We assume the max is >= min therefore we can return
return;
}

// Adjust maxValue if greater than the meta data's max value
if (rangeMax < static_cast<WorkingType>(aVPair.attributeValue))
if (rangeMax < Value)
{
maxValue = rangeMax;
// We assume the metadata's max value respects the odd size integers limits so we can return
return;
}
}

// Cap based on type-enforced maximum value (and minnimum for signed types)
if constexpr (std::is_signed<WorkingType>::value)
if (minValue > Value)
{
// Cap on max value, check for comparison to the WorkingType size and check for overflow
if (static_cast<WorkingType>(aVPair.attributeValue) > maxValue || aVPair.attributeValue & ~static_cast<uint64_t>(maxValue))
{
// We treat overflows as > Max value since the wrong type is being used and we cannot determine the actual value
aVPair.attributeValue = static_cast<std::make_unsigned_t<WorkingType>>(maxValue);
}
Value = minValue;
}
else
else if (maxValue < Value)
{
if (aVPair.attributeValue > maxValue)
{
aVPair.attributeValue = maxValue;
}
Value = maxValue;
}
}

Expand All @@ -144,60 +166,71 @@ CHIP_ERROR ValidateAttributePath(EndpointId endpoint, ClusterId cluster, Attribu
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
}

// There should never be more than one populated value in an ExtensionFieldSet
VerifyOrReturnError(IsOnlyOneValuePopulated(aVPair), CHIP_ERROR_INVALID_ARGUMENT);

switch (metadata->attributeType)
{
case ZCL_BOOLEAN_ATTRIBUTE_TYPE:
case ZCL_BITMAP8_ATTRIBUTE_TYPE:
case ZCL_INT8U_ATTRIBUTE_TYPE:
CapAttributeID<uint8_t>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueUnsigned8.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<uint8_t>(aVPair.valueUnsigned8.Value(), metadata);
break;
case ZCL_BITMAP16_ATTRIBUTE_TYPE:
case ZCL_INT16U_ATTRIBUTE_TYPE:
CapAttributeID<uint16_t>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueUnsigned16.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<uint16_t>(aVPair.valueUnsigned16.Value(), metadata);
break;
case ZCL_INT24U_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<3, false>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueUnsigned32.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<OddSizedInteger<3, false>>(aVPair.valueUnsigned32.Value(), metadata);
break;
case ZCL_BITMAP32_ATTRIBUTE_TYPE:
case ZCL_INT32U_ATTRIBUTE_TYPE:
CapAttributeID<uint32_t>(aVPair, metadata);
break;
case ZCL_INT40U_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<5, false>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueUnsigned32.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<uint32_t>(aVPair.valueUnsigned32.Value(), metadata);
break;
case ZCL_INT48U_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<6, false>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueUnsigned64.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<OddSizedInteger<6, false>>(aVPair.valueUnsigned64.Value(), metadata);
break;
case ZCL_INT56U_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<7, false>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueUnsigned64.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<OddSizedInteger<7, false>>(aVPair.valueUnsigned64.Value(), metadata);
break;
case ZCL_BITMAP64_ATTRIBUTE_TYPE:
case ZCL_INT64U_ATTRIBUTE_TYPE:
CapAttributeID<uint64_t>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueUnsigned64.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<uint64_t>(aVPair.valueUnsigned64.Value(), metadata);
break;
case ZCL_INT8S_ATTRIBUTE_TYPE:
CapAttributeID<int8_t>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueSigned8.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<int8_t>(aVPair.valueSigned8.Value(), metadata);
break;
case ZCL_INT16S_ATTRIBUTE_TYPE: // fallthrough
CapAttributeID<int16_t>(aVPair, metadata);
case ZCL_INT16S_ATTRIBUTE_TYPE:
VerifyOrReturnError(aVPair.valueSigned16.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<int16_t>(aVPair.valueSigned16.Value(), metadata);
break;
case ZCL_INT24S_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<3, true>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueSigned32.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<OddSizedInteger<3, true>>(aVPair.valueSigned32.Value(), metadata);
break;
case ZCL_INT32S_ATTRIBUTE_TYPE:
CapAttributeID<int32_t>(aVPair, metadata);
break;
case ZCL_INT40S_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<5, true>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueSigned32.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<int32_t>(aVPair.valueSigned32.Value(), metadata);
break;
case ZCL_INT48S_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<6, true>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueSigned64.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<OddSizedInteger<6, true>>(aVPair.valueSigned64.Value(), metadata);
break;
case ZCL_INT56S_ATTRIBUTE_TYPE:
CapAttributeID<OddSizedInteger<7, true>>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueSigned64.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<OddSizedInteger<7, true>>(aVPair.valueSigned64.Value(), metadata);
break;
case ZCL_INT64S_ATTRIBUTE_TYPE:
CapAttributeID<int64_t>(aVPair, metadata);
VerifyOrReturnError(aVPair.valueSigned64.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
CapAttributeID<int64_t>(aVPair.valueSigned64.Value(), metadata);
break;
default:
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
Expand Down
Loading

0 comments on commit 6c3dcad

Please sign in to comment.