LCOV - code coverage report
Current view: top level - app/util - attribute-table.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 0 85 0.0 %
Date: 2024-02-15 08:20:41 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /**
       2             :  *
       3             :  *    Copyright (c) 2020 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             : // this file contains all the common includes for clusters in the zcl-util
      19             : 
      20             : #include <app/util/attribute-storage.h>
      21             : 
      22             : // for pulling in defines dealing with EITHER server or client
      23             : #include "app/util/common.h"
      24             : #include <app/util/config.h>
      25             : #include <app/util/generic-callbacks.h>
      26             : #include <app/util/odd-sized-integers.h>
      27             : #include <lib/core/CHIPConfig.h>
      28             : 
      29             : #include <app/reporting/reporting.h>
      30             : #include <protocols/interaction_model/Constants.h>
      31             : 
      32             : using chip::Protocols::InteractionModel::Status;
      33             : 
      34             : using namespace chip;
      35             : 
      36           0 : Status emAfWriteAttributeExternal(EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * dataPtr,
      37             :                                   EmberAfAttributeType dataType)
      38             : {
      39           0 :     return emAfWriteAttribute(endpoint, cluster, attributeID, dataPtr, dataType, false /* override read-only */);
      40             : }
      41             : 
      42           0 : Status emberAfWriteAttribute(EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * dataPtr,
      43             :                              EmberAfAttributeType dataType)
      44             : {
      45           0 :     return emAfWriteAttribute(endpoint, cluster, attributeID, dataPtr, dataType, true /* override read-only */);
      46             : }
      47             : 
      48             : //------------------------------------------------------------------------------
      49             : // Internal Functions
      50             : 
      51             : // Helper for determining whether a value is a null value.
      52             : template <typename T>
      53           0 : static bool IsNullValue(const uint8_t * data)
      54             : {
      55             :     using Traits = app::NumericAttributeTraits<T>;
      56             :     // We don't know how data is aligned, so safely copy it over to the relevant
      57             :     // StorageType value.
      58             :     typename Traits::StorageType val;
      59           0 :     memcpy(&val, data, sizeof(val));
      60           0 :     return Traits::IsNullValue(val);
      61             : }
      62             : 
      63           0 : static bool IsNullValue(const uint8_t * data, uint16_t dataLen, bool isAttributeSigned)
      64             : {
      65           0 :     if (dataLen > 4)
      66             :     {
      67             :         // We don't support this, just like emberAfCompareValues does not.
      68           0 :         return false;
      69             :     }
      70             : 
      71           0 :     switch (dataLen)
      72             :     {
      73           0 :     case 1: {
      74           0 :         if (isAttributeSigned)
      75             :         {
      76           0 :             return IsNullValue<int8_t>(data);
      77             :         }
      78           0 :         return IsNullValue<uint8_t>(data);
      79             :     }
      80           0 :     case 2: {
      81           0 :         if (isAttributeSigned)
      82             :         {
      83           0 :             return IsNullValue<int16_t>(data);
      84             :         }
      85           0 :         return IsNullValue<uint16_t>(data);
      86             :     }
      87           0 :     case 3: {
      88           0 :         if (isAttributeSigned)
      89             :         {
      90           0 :             return IsNullValue<app::OddSizedInteger<3, true>>(data);
      91             :         }
      92           0 :         return IsNullValue<app::OddSizedInteger<3, false>>(data);
      93             :     }
      94           0 :     case 4: {
      95           0 :         if (isAttributeSigned)
      96             :         {
      97           0 :             return IsNullValue<int32_t>(data);
      98             :         }
      99           0 :         return IsNullValue<uint32_t>(data);
     100             :     }
     101             :     }
     102             : 
     103             :     // Not reached.
     104           0 :     return false;
     105             : }
     106             : 
     107           0 : Status emAfWriteAttribute(EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * data,
     108             :                           EmberAfAttributeType dataType, bool overrideReadOnlyAndDataType)
     109             : {
     110           0 :     const EmberAfAttributeMetadata * metadata = nullptr;
     111             :     EmberAfAttributeSearchRecord record;
     112           0 :     record.endpoint    = endpoint;
     113           0 :     record.clusterId   = cluster;
     114           0 :     record.attributeId = attributeID;
     115           0 :     Status status      = emAfReadOrWriteAttribute(&record, &metadata,
     116             :                                                   nullptr, // buffer
     117             :                                                   0,       // buffer size
     118             :                                                   false);  // write?
     119             : 
     120             :     // if we dont support that attribute
     121           0 :     if (metadata == nullptr)
     122             :     {
     123           0 :         ChipLogProgress(Zcl, "%p ep %x clus " ChipLogFormatMEI " attr " ChipLogFormatMEI " not supported", "WRITE ERR: ", endpoint,
     124             :                         ChipLogValueMEI(cluster), ChipLogValueMEI(attributeID));
     125           0 :         return status;
     126             :     }
     127             : 
     128             :     // if the data type specified by the caller is incorrect
     129           0 :     if (!(overrideReadOnlyAndDataType))
     130             :     {
     131           0 :         if (dataType != metadata->attributeType)
     132             :         {
     133           0 :             ChipLogProgress(Zcl, "%p invalid data type", "WRITE ERR: ");
     134           0 :             return Status::InvalidDataType;
     135             :         }
     136             : 
     137           0 :         if (metadata->IsReadOnly())
     138             :         {
     139           0 :             ChipLogProgress(Zcl, "%p attr not writable", "WRITE ERR: ");
     140           0 :             return Status::UnsupportedWrite;
     141             :         }
     142             :     }
     143             : 
     144             :     // if the value the attribute is being set to is out of range
     145             :     // return Status::ConstraintError
     146           0 :     if ((metadata->mask & ATTRIBUTE_MASK_MIN_MAX) != 0U)
     147             :     {
     148           0 :         EmberAfDefaultAttributeValue minv = metadata->defaultValue.ptrToMinMaxValue->minValue;
     149           0 :         EmberAfDefaultAttributeValue maxv = metadata->defaultValue.ptrToMinMaxValue->maxValue;
     150           0 :         uint16_t dataLen                  = emberAfAttributeSize(metadata);
     151             :         const uint8_t * minBytes;
     152             :         const uint8_t * maxBytes;
     153           0 :         if (dataLen <= 2)
     154             :         {
     155             :             static_assert(sizeof(minv.defaultValue) == 2, "if statement relies on size of minv.defaultValue being 2");
     156             :             static_assert(sizeof(maxv.defaultValue) == 2, "if statement relies on size of maxv.defaultValue being 2");
     157           0 :             minBytes = reinterpret_cast<const uint8_t *>(&(minv.defaultValue));
     158           0 :             maxBytes = reinterpret_cast<const uint8_t *>(&(maxv.defaultValue));
     159             : // On big endian cpu with length 1 only the second byte counts
     160             : #if (CHIP_CONFIG_BIG_ENDIAN_TARGET)
     161             :             if (dataLen == 1)
     162             :             {
     163             :                 minBytes++;
     164             :                 maxBytes++;
     165             :             }
     166             : #endif // CHIP_CONFIG_BIG_ENDIAN_TARGET
     167             :         }
     168             :         else
     169             :         {
     170           0 :             minBytes = minv.ptrToDefaultValue;
     171           0 :             maxBytes = maxv.ptrToDefaultValue;
     172             :         }
     173             : 
     174           0 :         bool isAttributeSigned = emberAfIsTypeSigned(metadata->attributeType);
     175           0 :         bool isOutOfRange      = emberAfCompareValues(minBytes, data, dataLen, isAttributeSigned) == 1 ||
     176           0 :             emberAfCompareValues(maxBytes, data, dataLen, isAttributeSigned) == -1;
     177             : 
     178           0 :         if (isOutOfRange &&
     179             :             // null value is always in-range for a nullable attribute.
     180           0 :             (!metadata->IsNullable() || !IsNullValue(data, dataLen, isAttributeSigned)))
     181             :         {
     182           0 :             return Status::ConstraintError;
     183             :         }
     184             :     }
     185             : 
     186           0 :     const app::ConcreteAttributePath attributePath(endpoint, cluster, attributeID);
     187             : 
     188             :     // Pre write attribute callback for all attribute changes,
     189             :     // regardless of cluster.
     190             :     Protocols::InteractionModel::Status imStatus =
     191           0 :         MatterPreAttributeChangeCallback(attributePath, dataType, emberAfAttributeSize(metadata), data);
     192           0 :     if (imStatus != Protocols::InteractionModel::Status::Success)
     193             :     {
     194           0 :         return imStatus;
     195             :     }
     196             : 
     197             :     // Pre-write attribute callback specific
     198             :     // to the cluster that the attribute lives in.
     199           0 :     status = emAfClusterPreAttributeChangedCallback(attributePath, dataType, emberAfAttributeSize(metadata), data);
     200             : 
     201             :     // Ignore the following write operation and return success
     202           0 :     if (status == Status::WriteIgnored)
     203             :     {
     204           0 :         return Status::Success;
     205             :     }
     206             : 
     207           0 :     if (status != Status::Success)
     208             :     {
     209           0 :         return status;
     210             :     }
     211             : 
     212             :     // write the attribute
     213           0 :     status = emAfReadOrWriteAttribute(&record,
     214             :                                       nullptr, // metadata
     215             :                                       data,
     216             :                                       0,     // buffer size - unused
     217             :                                       true); // write?
     218             : 
     219           0 :     if (status != Status::Success)
     220             :     {
     221           0 :         return status;
     222             :     }
     223             : 
     224             :     // Save the attribute to persistent storage if needed
     225             :     // The callee will weed out attributes that do not need to be stored.
     226           0 :     emAfSaveAttributeToStorageIfNeeded(data, endpoint, cluster, metadata);
     227             : 
     228           0 :     MatterReportingAttributeChangeCallback(endpoint, cluster, attributeID);
     229             : 
     230             :     // Post write attribute callback for all attributes changes, regardless
     231             :     // of cluster.
     232           0 :     MatterPostAttributeChangeCallback(attributePath, dataType, emberAfAttributeSize(metadata), data);
     233             : 
     234             :     // Post-write attribute callback specific
     235             :     // to the cluster that the attribute lives in.
     236           0 :     emAfClusterAttributeChangedCallback(attributePath);
     237             : 
     238           0 :     return Status::Success;
     239             : }
     240             : 
     241           0 : Status emberAfReadAttribute(EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * dataPtr, uint16_t readLength)
     242             : {
     243           0 :     const EmberAfAttributeMetadata * metadata = nullptr;
     244             :     EmberAfAttributeSearchRecord record;
     245             :     Status status;
     246           0 :     record.endpoint    = endpoint;
     247           0 :     record.clusterId   = cluster;
     248           0 :     record.attributeId = attributeID;
     249           0 :     status             = emAfReadOrWriteAttribute(&record, &metadata, dataPtr, readLength,
     250             :                                                   false); // write?
     251             : 
     252             :     // failed, print debug info
     253           0 :     if (status == Status::ResourceExhausted)
     254             :     {
     255           0 :         ChipLogProgress(Zcl, "READ: attribute size too large for caller");
     256             :     }
     257             : 
     258           0 :     return status;
     259             : }

Generated by: LCOV version 1.14