Line data Source code
1 : /** 2 : * 3 : * Copyright (c) 2020-2021 Project CHIP Authors 4 : * 5 : * Licensed under the Apache License, Version 2.0 (the "License"); 6 : * you may not use this file except in compliance with the License. 7 : * You may obtain a copy of the License at 8 : * 9 : * http://www.apache.org/licenses/LICENSE-2.0 10 : * 11 : * Unless required by applicable law or agreed to in writing, software 12 : * distributed under the License is distributed on an "AS IS" BASIS, 13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 : * See the License for the specific language governing permissions and 15 : * limitations under the License. 16 : */ 17 : 18 : #include "app/util/common.h" 19 : #include <app-common/zap-generated/attribute-type.h> 20 : #include <app-common/zap-generated/attributes/Accessors.h> 21 : #include <app-common/zap-generated/ids/Clusters.h> 22 : #include <app-common/zap-generated/print-cluster.h> 23 : #include <app/util/af.h> 24 : #include <app/util/config.h> 25 : #include <app/util/generic-callbacks.h> 26 : #include <lib/core/CHIPConfig.h> 27 : #include <lib/core/CHIPEncoding.h> 28 : #include <protocols/interaction_model/StatusCode.h> 29 : 30 : // TODO: figure out a clear path for compile-time codegen 31 : #include <app/PluginApplicationCallbacks.h> 32 : 33 : #ifdef MATTER_DM_PLUGIN_GROUPS_SERVER 34 : #include <app/clusters/groups-server/groups-server.h> 35 : #endif // MATTER_DM_PLUGIN_GROUPS_SERVER 36 : 37 : using namespace chip; 38 : 39 : using chip::Protocols::InteractionModel::Status; 40 : 41 : //------------------------------------------------------------------------------ 42 : // Forward Declarations 43 : 44 : //------------------------------------------------------------------------------ 45 : // Globals 46 : 47 : const EmberAfClusterName zclClusterNames[] = { 48 : CLUSTER_IDS_TO_NAMES // defined in print-cluster.h 49 : { kInvalidClusterId, nullptr }, // terminator 50 : }; 51 : 52 : #ifdef MATTER_DM_GENERATED_PLUGIN_TICK_FUNCTION_DECLARATIONS 53 : MATTER_DM_GENERATED_PLUGIN_TICK_FUNCTION_DECLARATIONS 54 : #endif 55 : 56 : //------------------------------------------------------------------------------ 57 : 58 : // Is the device identifying? 59 0 : bool emberAfIsDeviceIdentifying(EndpointId endpoint) 60 : { 61 : #ifdef ZCL_USING_IDENTIFY_CLUSTER_SERVER 62 : uint16_t identifyTime; 63 : Status status = app::Clusters::Identify::Attributes::IdentifyTime::Get(endpoint, &identifyTime); 64 : return (status == Status::Success && 0 < identifyTime); 65 : #else 66 0 : return false; 67 : #endif 68 : } 69 : 70 : // Calculates difference. See EmberAfDifferenceType for the maximum data size 71 : // that this function will support. 72 0 : EmberAfDifferenceType emberAfGetDifference(uint8_t * pData, EmberAfDifferenceType value, uint8_t dataSize) 73 : { 74 0 : EmberAfDifferenceType value2 = 0, diff; 75 : uint8_t i; 76 : 77 : // only support data types up to 8 bytes 78 0 : if (dataSize > sizeof(EmberAfDifferenceType)) 79 : { 80 0 : return 0; 81 : } 82 : 83 : // get the value 84 0 : for (i = 0; i < dataSize; i++) 85 : { 86 0 : value2 = value2 << 8; 87 : #if (CHIP_CONFIG_BIG_ENDIAN_TARGET) 88 : value2 += pData[i]; 89 : #else // BIGENDIAN 90 0 : value2 += pData[dataSize - i - 1]; 91 : #endif // BIGENDIAN 92 : } 93 : 94 0 : if (value > value2) 95 : { 96 0 : diff = value - value2; 97 : } 98 : else 99 : { 100 0 : diff = value2 - value; 101 : } 102 : 103 0 : return diff; 104 : } 105 : 106 : // **************************************** 107 : // Initialize Clusters 108 : // **************************************** 109 15 : void emberAfInit() 110 : { 111 15 : emberAfInitializeAttributes(kInvalidEndpointId); 112 : 113 : MATTER_PLUGINS_INIT 114 : 115 15 : emAfCallInits(); 116 15 : } 117 : 118 : // Cluster init functions that don't have a cluster implementation to define 119 : // them in. 120 0 : void MatterBallastConfigurationPluginServerInitCallback() {} 121 0 : void MatterBooleanStatePluginServerInitCallback() {} 122 0 : void MatterElectricalMeasurementPluginServerInitCallback() {} 123 0 : void MatterRelativeHumidityMeasurementPluginServerInitCallback() {} 124 0 : void MatterIlluminanceMeasurementPluginServerInitCallback() {} 125 0 : void MatterBinaryInputBasicPluginServerInitCallback() {} 126 0 : void MatterPressureMeasurementPluginServerInitCallback() {} 127 0 : void MatterTemperatureMeasurementPluginServerInitCallback() {} 128 0 : void MatterFlowMeasurementPluginServerInitCallback() {} 129 0 : void MatterOnOffSwitchConfigurationPluginServerInitCallback() {} 130 0 : void MatterThermostatUserInterfaceConfigurationPluginServerInitCallback() {} 131 0 : void MatterBridgedDeviceBasicInformationPluginServerInitCallback() {} 132 0 : void MatterPowerConfigurationPluginServerInitCallback() {} 133 0 : void MatterPowerProfilePluginServerInitCallback() {} 134 0 : void MatterPulseWidthModulationPluginServerInitCallback() {} 135 0 : void MatterAlarmsPluginServerInitCallback() {} 136 0 : void MatterTimePluginServerInitCallback() {} 137 0 : void MatterAclPluginServerInitCallback() {} 138 0 : void MatterPollControlPluginServerInitCallback() {} 139 0 : void MatterUnitLocalizationPluginServerInitCallback() {} 140 0 : void MatterProxyValidPluginServerInitCallback() {} 141 0 : void MatterProxyDiscoveryPluginServerInitCallback() {} 142 0 : void MatterProxyConfigurationPluginServerInitCallback() {} 143 0 : void MatterFanControlPluginServerInitCallback() {} 144 0 : void MatterActivatedCarbonFilterMonitoringPluginServerInitCallback() {} 145 0 : void MatterHepaFilterMonitoringPluginServerInitCallback() {} 146 0 : void MatterAirQualityPluginServerInitCallback() {} 147 0 : void MatterCarbonMonoxideConcentrationMeasurementPluginServerInitCallback() {} 148 0 : void MatterCarbonDioxideConcentrationMeasurementPluginServerInitCallback() {} 149 0 : void MatterFormaldehydeConcentrationMeasurementPluginServerInitCallback() {} 150 0 : void MatterNitrogenDioxideConcentrationMeasurementPluginServerInitCallback() {} 151 0 : void MatterOzoneConcentrationMeasurementPluginServerInitCallback() {} 152 0 : void MatterPm10ConcentrationMeasurementPluginServerInitCallback() {} 153 0 : void MatterPm1ConcentrationMeasurementPluginServerInitCallback() {} 154 0 : void MatterPm25ConcentrationMeasurementPluginServerInitCallback() {} 155 0 : void MatterRadonConcentrationMeasurementPluginServerInitCallback() {} 156 0 : void MatterTotalVolatileOrganicCompoundsConcentrationMeasurementPluginServerInitCallback() {} 157 0 : void MatterRvcRunModePluginServerInitCallback() {} 158 0 : void MatterRvcCleanModePluginServerInitCallback() {} 159 0 : void MatterDishwasherModePluginServerInitCallback() {} 160 0 : void MatterLaundryWasherModePluginServerInitCallback() {} 161 0 : void MatterRefrigeratorAndTemperatureControlledCabinetModePluginServerInitCallback() {} 162 0 : void MatterOperationalStatePluginServerInitCallback() {} 163 0 : void MatterRvcOperationalStatePluginServerInitCallback() {} 164 0 : void MatterOvenModePluginServerInitCallback() {} 165 0 : void MatterOvenCavityOperationalStatePluginServerInitCallback() {} 166 0 : void MatterDishwasherAlarmPluginServerInitCallback() {} 167 0 : void MatterMicrowaveOvenModePluginServerInitCallback() {} 168 0 : void MatterDeviceEnergyManagementModePluginServerInitCallback() {} 169 0 : void MatterEnergyEvseModePluginServerInitCallback() {} 170 0 : void MatterElectricalEnergyMeasurementPluginServerInitCallback() {} 171 0 : void MatterElectricalPowerMeasurementPluginServerInitCallback() {} 172 : // **************************************** 173 : // Print out information about each cluster 174 : // **************************************** 175 : 176 0 : uint16_t emberAfFindClusterNameIndex(ClusterId cluster) 177 : { 178 : static_assert(sizeof(ClusterId) == 4, "May need to adjust our index type or somehow define it in terms of cluster id type"); 179 0 : uint16_t index = 0; 180 0 : while (zclClusterNames[index].id != kInvalidClusterId) 181 : { 182 0 : if (zclClusterNames[index].id == cluster) 183 : { 184 0 : return index; 185 : } 186 0 : index++; 187 : } 188 0 : return 0xFFFF; 189 : } 190 : 191 0 : void emberAfCopyString(uint8_t * dest, const uint8_t * src, size_t size) 192 : { 193 0 : if (src == nullptr) 194 : { 195 0 : dest[0] = 0; // Zero out the length of string 196 : } 197 0 : else if (src[0] == 0xFF) 198 : { 199 0 : dest[0] = src[0]; 200 : } 201 : else 202 : { 203 0 : uint8_t length = emberAfStringLength(src); 204 0 : if (size < length) 205 : { 206 : // Since we have checked that size < length, size must be able to fit into the type of length. 207 0 : length = static_cast<decltype(length)>(size); 208 : } 209 0 : memmove(dest + 1, src + 1, length); 210 0 : dest[0] = length; 211 : } 212 0 : } 213 : 214 0 : void emberAfCopyLongString(uint8_t * dest, const uint8_t * src, size_t size) 215 : { 216 0 : if (src == nullptr) 217 : { 218 0 : dest[0] = dest[1] = 0; // Zero out the length of string 219 : } 220 0 : else if ((src[0] == 0xFF) && (src[1] == 0xFF)) 221 : { 222 0 : dest[0] = 0xFF; 223 0 : dest[1] = 0xFF; 224 : } 225 : else 226 : { 227 0 : uint16_t length = emberAfLongStringLength(src); 228 0 : if (size < length) 229 : { 230 : // Since we have checked that size < length, size must be able to fit into the type of length. 231 0 : length = static_cast<decltype(length)>(size); 232 : } 233 0 : memmove(dest + 2, src + 2, length); 234 0 : Encoding::LittleEndian::Put16(dest, length); 235 : } 236 0 : } 237 : 238 : #if (CHIP_CONFIG_BIG_ENDIAN_TARGET) 239 : #define EM_BIG_ENDIAN true 240 : #else 241 : #define EM_BIG_ENDIAN false 242 : #endif 243 : 244 : // You can pass in val1 as NULL, which will assume that it is 245 : // pointing to an array of all zeroes. This is used so that 246 : // default value of NULL is treated as all zeroes. 247 0 : int8_t emberAfCompareValues(const uint8_t * val1, const uint8_t * val2, uint16_t len, bool signedNumber) 248 : { 249 0 : if (len == 0) 250 : { 251 : // no length means nothing to compare. Shouldn't even happen, since len is sizeof(some-integer-type). 252 0 : return 0; 253 : } 254 : 255 0 : if (signedNumber) 256 : { // signed number comparison 257 0 : if (len <= 4) 258 : { // only number with 32-bits or less is supported 259 0 : int32_t accum1 = 0x0; 260 0 : int32_t accum2 = 0x0; 261 0 : int32_t all1s = -1; 262 : 263 0 : for (uint16_t i = 0; i < len; i++) 264 : { 265 0 : uint8_t j = (val1 == nullptr ? 0 : (EM_BIG_ENDIAN ? val1[i] : val1[(len - 1) - i])); 266 0 : accum1 |= j << (8 * (len - 1 - i)); 267 : 268 0 : uint8_t k = (EM_BIG_ENDIAN ? val2[i] : val2[(len - 1) - i]); 269 0 : accum2 |= k << (8 * (len - 1 - i)); 270 : } 271 : 272 : // sign extending, no need for 32-bits numbers 273 0 : if (len < 4) 274 : { 275 0 : if ((accum1 & (1 << (8 * len - 1))) != 0) 276 : { // check sign 277 0 : accum1 |= all1s - ((1 << (len * 8)) - 1); 278 : } 279 0 : if ((accum2 & (1 << (8 * len - 1))) != 0) 280 : { // check sign 281 0 : accum2 |= all1s - ((1 << (len * 8)) - 1); 282 : } 283 : } 284 : 285 0 : if (accum1 > accum2) 286 : { 287 0 : return 1; 288 : } 289 0 : if (accum1 < accum2) 290 : { 291 0 : return -1; 292 : } 293 : 294 0 : return 0; 295 : } 296 : 297 : // not supported 298 0 : return 0; 299 : } 300 : 301 : // regular unsigned number comparison 302 0 : for (uint16_t i = 0; i < len; i++) 303 : { 304 0 : uint8_t j = (val1 == nullptr ? 0 : (EM_BIG_ENDIAN ? val1[i] : val1[(len - 1) - i])); 305 0 : uint8_t k = (EM_BIG_ENDIAN ? val2[i] : val2[(len - 1) - i]); 306 : 307 0 : if (j > k) 308 : { 309 0 : return 1; 310 : } 311 0 : if (k > j) 312 : { 313 0 : return -1; 314 : } 315 : } 316 0 : return 0; 317 : } 318 : 319 : // Zigbee spec says types between signed 8 bit and signed 64 bit 320 0 : bool emberAfIsTypeSigned(EmberAfAttributeType dataType) 321 : { 322 0 : return (dataType >= ZCL_INT8S_ATTRIBUTE_TYPE && dataType <= ZCL_INT64S_ATTRIBUTE_TYPE); 323 : } 324 : 325 450 : bool emberAfContainsAttribute(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId) 326 : { 327 450 : return (emberAfGetServerAttributeIndexByAttributeId(endpoint, clusterId, attributeId) != UINT16_MAX); 328 : } 329 : 330 0 : bool emberAfIsKnownVolatileAttribute(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId) 331 : { 332 0 : const EmberAfAttributeMetadata * metadata = emberAfLocateAttributeMetadata(endpoint, clusterId, attributeId); 333 : 334 0 : if (metadata == nullptr) 335 : { 336 0 : return false; 337 : } 338 : 339 0 : return !metadata->IsAutomaticallyPersisted() && !metadata->IsExternal(); 340 : }