@@ -26,47 +26,24 @@ namespace {
26
26
using ConcreteAttributePath = app::ConcreteAttributePath;
27
27
using AttributeValuePairType = app::Clusters::ScenesManagement::Structs::AttributeValuePair::Type;
28
28
29
- // / IsAttributeTypeValid
30
- // / @brief Check if the attribute type is valid for a scene extension field value according to the spec.
31
- // / @param type Type of the attribute's metadata
32
- // / @return
33
- bool IsSceneValidAttributeType (EmberAfAttributeType type)
34
- {
35
- return (type == ZCL_INT8U_ATTRIBUTE_TYPE || type == ZCL_INT16U_ATTRIBUTE_TYPE || type == ZCL_INT32U_ATTRIBUTE_TYPE ||
36
- type == ZCL_INT64U_ATTRIBUTE_TYPE || type == ZCL_INT8S_ATTRIBUTE_TYPE || type == ZCL_INT16S_ATTRIBUTE_TYPE ||
37
- type == ZCL_INT32S_ATTRIBUTE_TYPE || type == ZCL_INT64S_ATTRIBUTE_TYPE);
38
- }
39
-
40
- // / IsSignedAttribute
41
- // / @brief Compare the attribute type to the signed attribute types in ZCL and return true if it is signed.
42
- // / @param attributeType metadata's attribute type
43
- // / @return
44
- bool IsSignedAttribute (EmberAfAttributeType attributeType)
45
- {
46
- return (attributeType >= ZCL_INT8S_ATTRIBUTE_TYPE && attributeType <= ZCL_INT64S_ATTRIBUTE_TYPE);
47
- }
48
-
49
29
// / ConvertByteArrayToUInt64
50
30
// / @brief Helper function to convert a byte array to a uint64_t value
51
31
// / @param EmberAfDefaultAttributeValue & defaultValue
52
32
// / @param len Length of the byte array
53
- // / @return uint64_t Value
33
+ // / @return uint64_t or int64_t Value
54
34
// / @note The attribute table supports 8 bytes only for unsigned integers, 4 bytes is the maximum for signed integers
55
- uint64_t ConvertByteArrayToUInt64 (const EmberAfDefaultAttributeValue & defaultValue, uint16_t len)
35
+ template <typename Type>
36
+ Type ConvertByteArrayToType (const EmberAfDefaultAttributeValue & defaultValue, uint16_t len)
56
37
{
57
38
if (len <= 2 )
58
39
{
59
- return static_cast <uint64_t >(defaultValue.defaultValue );
40
+ return static_cast <Type >(defaultValue.defaultValue );
60
41
}
61
42
else
62
43
{
63
- uint64_t result = 0 ;
64
- const uint8_t * val = defaultValue.ptrToDefaultValue ;
65
- for (size_t i = 0 ; i < len; i++)
66
- {
67
- result = (result << 8 ) | val[(CHIP_CONFIG_BIG_ENDIAN_TARGET ? i : (len - 1 ) - i)];
68
- }
69
- return result;
44
+ Type sValue = 0 ;
45
+ memcpy (&sValue , defaultValue.ptrToDefaultValue , sizeof (Type));
46
+ return app::NumericAttributeTraits<Type>::StorageToWorking (sValue );
70
47
}
71
48
}
72
49
@@ -76,32 +53,37 @@ uint64_t ConvertByteArrayToUInt64(const EmberAfDefaultAttributeValue & defaultVa
76
53
// / @param[in] aVPair AttributeValuePairType
77
54
// / @param[in] metadata EmberAfAttributeMetadata
78
55
// /
56
+ template <typename Type>
79
57
void CapAttributeID (AttributeValuePairType & aVPair, const EmberAfAttributeMetadata * metadata)
80
58
{
81
59
// Calculate the maximum value that can be represented with the given number of bytes
82
- uint64_t maxValue = 0 ;
60
+ Type maxValue = 0 ;
83
61
84
62
// Check if the attribute type is signed
85
- if (IsSignedAttribute ( metadata->attributeType ))
63
+ if (metadata->IsSignedIntegerAttribute ( ))
86
64
{
87
- maxValue = ( 1ULL << (( emberAfAttributeSize (metadata) * 8 ) - 1 )) - 1 ;
65
+ maxValue = static_cast <Type>(( 1ULL << (emberAfAttributeSize (metadata) * 8 - 1 )) - 1 ) ;
88
66
}
89
67
else
90
68
{
91
- maxValue = ( 1ULL << (emberAfAttributeSize (metadata) * 8 )) - 1 ;
69
+ maxValue = static_cast <Type>(( 1ULL << (emberAfAttributeSize (metadata) * 8 )) - 1 ) ;
92
70
}
93
71
94
72
// Check metadata for min and max values
95
- if (( metadata->mask & ATTRIBUTE_MASK_MIN_MAX) && metadata-> defaultValue . ptrToMinMaxValue )
73
+ if (metadata->HasMinMax () )
96
74
{
97
75
const EmberAfAttributeMinMaxValue * minMaxValue = metadata->defaultValue .ptrToMinMaxValue ;
98
- uint64_t minVal = ConvertByteArrayToUInt64 (minMaxValue->minValue , emberAfAttributeSize (metadata));
99
- uint64_t maxVal = ConvertByteArrayToUInt64 (minMaxValue->maxValue , emberAfAttributeSize (metadata));
76
+ Type minVal = ConvertByteArrayToType<Type> (minMaxValue->minValue , emberAfAttributeSize (metadata));
77
+ Type maxVal = ConvertByteArrayToType<Type> (minMaxValue->maxValue , emberAfAttributeSize (metadata));
100
78
101
- // Cap based on minValue
102
- if (minVal > aVPair.attributeValue )
79
+ // Cap based on minimum value
80
+ if (minVal > static_cast <Type>( aVPair.attributeValue ) )
103
81
{
104
- aVPair.attributeValue = minVal;
82
+ uint64_t sValue = 0 ;
83
+ memcpy (&sValue , &minVal, sizeof (Type));
84
+ aVPair.attributeValue = app::NumericAttributeTraits<uint64_t >::StorageToWorking (sValue );
85
+ // We assume the max is >= min therefore we can return
86
+ return ;
105
87
}
106
88
107
89
// Adjust maxValue if greater than the meta data's max value
@@ -112,17 +94,31 @@ void CapAttributeID(AttributeValuePairType & aVPair, const EmberAfAttributeMetad
112
94
}
113
95
114
96
// Cap based on maximum value
115
- if (aVPair. attributeValue > maxValue )
97
+ if (metadata-> IsSignedIntegerAttribute () )
116
98
{
117
- aVPair.attributeValue = maxValue;
99
+ if (static_cast <int64_t >(aVPair.attributeValue ) > static_cast <int64_t >(maxValue))
100
+ {
101
+ uint64_t sValue = 0 ;
102
+ memcpy (&sValue , &maxValue, sizeof (Type));
103
+ aVPair.attributeValue = app::NumericAttributeTraits<uint64_t >::StorageToWorking (sValue );
104
+ }
105
+ }
106
+ else
107
+ {
108
+ if (static_cast <uint64_t >(aVPair.attributeValue ) > static_cast <uint64_t >(maxValue))
109
+ {
110
+ uint64_t sValue = 0 ;
111
+ memcpy (&sValue , &maxValue, sizeof (Type));
112
+ aVPair.attributeValue = app::NumericAttributeTraits<uint64_t >::StorageToWorking (sValue );
113
+ }
118
114
}
119
115
}
120
116
121
117
// / @brief Validate the attribute exists for a given cluster
122
118
// / @param[in] endpoint Endpoint ID
123
119
// / @param[in] clusterID Cluster ID
124
120
// / @param[in] aVPair AttributeValuePairType, will be mutated to cap the value if it is out of range
125
- // / @return CHIP_ERROR_UNSUPPORTED_ATTRIBUTE if the attribute does not exist for a given cluster or is not scenable
121
+ // / @return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute) if the attribute does not exist for a given cluster or is not scenable
126
122
// / @note This will allways fail for global list attributes. If we do want to make them scenable someday, we will need to
127
123
// / use a different validation method.
128
124
// TODO: Add check for "S" quality to determine if the attribute is scenable once suported :
@@ -133,17 +129,39 @@ CHIP_ERROR ValidateAttributePath(EndpointId endpoint, ClusterId cluster, Attribu
133
129
134
130
if (nullptr == metadata)
135
131
{
136
- return CHIP_ERROR_UNSUPPORTED_ATTRIBUTE ;
132
+ return CHIP_IM_GLOBAL_STATUS (UnsupportedAttribute) ;
137
133
}
138
134
139
- if (! IsSceneValidAttributeType ( metadata->attributeType ) )
135
+ switch ( metadata->attributeType )
140
136
{
141
- return CHIP_ERROR_UNSUPPORTED_ATTRIBUTE;
137
+ case ZCL_INT8U_ATTRIBUTE_TYPE:
138
+ CapAttributeID<uint8_t >(aVPair, metadata);
139
+ break ;
140
+ case ZCL_INT16U_ATTRIBUTE_TYPE:
141
+ CapAttributeID<uint16_t >(aVPair, metadata);
142
+ break ;
143
+ case ZCL_INT32U_ATTRIBUTE_TYPE:
144
+ CapAttributeID<uint32_t >(aVPair, metadata);
145
+ break ;
146
+ case ZCL_INT64U_ATTRIBUTE_TYPE:
147
+ CapAttributeID<uint64_t >(aVPair, metadata);
148
+ break ;
149
+ case ZCL_INT8S_ATTRIBUTE_TYPE:
150
+ CapAttributeID<int8_t >(aVPair, metadata);
151
+ break ;
152
+ case ZCL_INT16S_ATTRIBUTE_TYPE: // fallthrough
153
+ CapAttributeID<int16_t >(aVPair, metadata);
154
+ break ;
155
+ case ZCL_INT32S_ATTRIBUTE_TYPE:
156
+ CapAttributeID<int32_t >(aVPair, metadata);
157
+ break ;
158
+ case ZCL_INT64S_ATTRIBUTE_TYPE:
159
+ CapAttributeID<int64_t >(aVPair, metadata);
160
+ break ;
161
+ default :
162
+ return CHIP_IM_GLOBAL_STATUS (UnsupportedAttribute);
142
163
}
143
164
144
- // Cap value based on the attribute type size
145
- CapAttributeID (aVPair, metadata);
146
-
147
165
return CHIP_NO_ERROR;
148
166
}
149
167
} // namespace
0 commit comments