Matter SDK Coverage Report
Current view: top level - data-model-providers/codegen - CodegenDataModelProvider_Read.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 97.3 % 37 36
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2024 Project CHIP Authors
       3              :  *    All rights reserved.
       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              : #include <data-model-providers/codegen/CodegenDataModelProvider.h>
      18              : 
      19              : #include <optional>
      20              : #include <variant>
      21              : 
      22              : #include <access/AccessControl.h>
      23              : #include <access/Privilege.h>
      24              : #include <access/RequestPath.h>
      25              : #include <app-common/zap-generated/attribute-type.h>
      26              : #include <app/AttributeAccessInterface.h>
      27              : #include <app/AttributeAccessInterfaceRegistry.h>
      28              : #include <app/AttributeValueEncoder.h>
      29              : #include <app/GlobalAttributes.h>
      30              : #include <app/RequiredPrivilege.h>
      31              : #include <app/data-model/FabricScoped.h>
      32              : #include <app/util/af-types.h>
      33              : #include <app/util/attribute-metadata.h>
      34              : #include <app/util/attribute-storage-detail.h>
      35              : #include <app/util/attribute-storage-null-handling.h>
      36              : #include <app/util/attribute-storage.h>
      37              : #include <app/util/ember-global-attribute-access-interface.h>
      38              : #include <app/util/ember-io-storage.h>
      39              : #include <app/util/endpoint-config-api.h>
      40              : #include <app/util/odd-sized-integers.h>
      41              : #include <data-model-providers/codegen/EmberAttributeDataBuffer.h>
      42              : #include <data-model-providers/codegen/EmberMetadata.h>
      43              : #include <lib/core/CHIPError.h>
      44              : #include <lib/support/CodeUtils.h>
      45              : #include <lib/support/Span.h>
      46              : 
      47              : #include <zap-generated/endpoint_config.h>
      48              : 
      49              : namespace chip {
      50              : namespace app {
      51              : 
      52              : namespace {
      53              : 
      54              : using namespace chip::app::Compatibility::Internal;
      55              : using Protocols::InteractionModel::Status;
      56              : 
      57              : /// Attempts to read via an attribute access interface (AAI)
      58              : ///
      59              : /// If it returns a CHIP_ERROR, then this is a FINAL result (i.e. either failure or success).
      60              : ///
      61              : /// If it returns std::nullopt, then there is no AAI to handle the given path
      62              : /// and processing should figure out the value otherwise (generally from other ember data)
      63         2516 : std::optional<CHIP_ERROR> TryReadViaAccessInterface(const ConcreteAttributePath & path, AttributeAccessInterface * aai,
      64              :                                                     AttributeValueEncoder & encoder)
      65              : {
      66              :     // Processing can happen only if an attribute access interface actually exists..
      67         2516 :     if (aai == nullptr)
      68              :     {
      69           38 :         return std::nullopt;
      70              :     }
      71              : 
      72         2478 :     CHIP_ERROR err = aai->Read(path, encoder);
      73              : 
      74         2478 :     if (err != CHIP_NO_ERROR)
      75              :     {
      76              :         // Implementation of 8.4.3.2 of the spec for path expansion
      77          232 :         if (path.mExpanded && (err == CHIP_IM_GLOBAL_STATUS(UnsupportedRead)))
      78              :         {
      79            1 :             return CHIP_NO_ERROR;
      80              :         }
      81              : 
      82          231 :         return err;
      83              :     }
      84              : 
      85              :     // If the encoder tried to encode, then a value should have been written.
      86              :     //   - if encode, assume DONE (i.e. FINAL CHIP_NO_ERROR)
      87              :     //   - if no encode, say that processing must continue
      88         4492 :     return encoder.TriedEncode() ? std::make_optional(CHIP_NO_ERROR) : std::nullopt;
      89              : }
      90              : 
      91              : } // namespace
      92              : 
      93              : /// separated-out ReadAttribute implementation (given existing complexity)
      94              : ///
      95              : /// Generally will:
      96              : ///    - validate ACL (only for non-internal requests)
      97              : ///    - Try to read attribute via the AttributeAccessInterface
      98              : ///    - Try to read the value from ember RAM storage
      99         2521 : DataModel::ActionReturnStatus CodegenDataModelProvider::ReadAttribute(const DataModel::ReadAttributeRequest & request,
     100              :                                                                       AttributeValueEncoder & encoder)
     101              : {
     102         2521 :     ChipLogDetail(DataManagement,
     103              :                   "Reading attribute: Cluster=" ChipLogFormatMEI " Endpoint=0x%x AttributeId=" ChipLogFormatMEI " (expanded=%d)",
     104              :                   ChipLogValueMEI(request.path.mClusterId), request.path.mEndpointId, ChipLogValueMEI(request.path.mAttributeId),
     105              :                   request.path.mExpanded);
     106              : 
     107         2521 :     auto metadata = Ember::FindAttributeMetadata(request.path);
     108              : 
     109              :     // Explicit failure in finding a suitable metadata
     110         2521 :     if (const Status * status = std::get_if<Status>(&metadata))
     111              :     {
     112            5 :         VerifyOrDie((*status == Status::UnsupportedEndpoint) || //
     113              :                     (*status == Status::UnsupportedCluster) ||  //
     114              :                     (*status == Status::UnsupportedAttribute));
     115            5 :         return *status;
     116              :     }
     117              : 
     118              :     // Read via AAI
     119         2516 :     std::optional<CHIP_ERROR> aai_result;
     120         2516 :     if (const EmberAfCluster ** cluster = std::get_if<const EmberAfCluster *>(&metadata))
     121              :     {
     122          716 :         Compatibility::GlobalAttributeReader aai(*cluster);
     123          716 :         aai_result = TryReadViaAccessInterface(request.path, &aai, encoder);
     124          716 :     }
     125              :     else
     126              :     {
     127         3600 :         aai_result = TryReadViaAccessInterface(
     128         1800 :             request.path, AttributeAccessInterfaceRegistry::Instance().Get(request.path.mEndpointId, request.path.mClusterId),
     129              :             encoder);
     130              :     }
     131         2516 :     VerifyOrReturnError(!aai_result.has_value(), *aai_result);
     132              : 
     133           38 :     if (!std::holds_alternative<const EmberAfAttributeMetadata *>(metadata))
     134              :     {
     135              :         // if we only got a cluster, this was for a global attribute. We cannot read ember attributes
     136              :         // at this point, so give up (although GlobalAttributeReader should have returned something here).
     137            0 :         chipDie();
     138              :     }
     139           38 :     const EmberAfAttributeMetadata * attributeMetadata = std::get<const EmberAfAttributeMetadata *>(metadata);
     140              : 
     141              :     // At this point, we have to use ember directly to read the data.
     142              :     EmberAfAttributeSearchRecord record;
     143           38 :     record.endpoint                            = request.path.mEndpointId;
     144           38 :     record.clusterId                           = request.path.mClusterId;
     145           38 :     record.attributeId                         = request.path.mAttributeId;
     146           38 :     Protocols::InteractionModel::Status status = emAfReadOrWriteAttribute(
     147           38 :         &record, &attributeMetadata, gEmberAttributeIOBufferSpan.data(), static_cast<uint16_t>(gEmberAttributeIOBufferSpan.size()),
     148              :         /* write = */ false);
     149              : 
     150           38 :     if (status != Protocols::InteractionModel::Status::Success)
     151              :     {
     152            2 :         return CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(status);
     153              :     }
     154              : 
     155           36 :     VerifyOrReturnError(attributeMetadata != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     156              : 
     157           36 :     MutableByteSpan data = gEmberAttributeIOBufferSpan;
     158           36 :     Ember::EmberAttributeDataBuffer emberData(attributeMetadata, data);
     159           36 :     return encoder.Encode(emberData);
     160              : }
     161              : 
     162              : } // namespace app
     163              : } // namespace chip
        

Generated by: LCOV version 2.0-1