From 5384564df0c1e2e08092f13866a0fd30d34af22d Mon Sep 17 00:00:00 2001 From: Matt Hazley Date: Thu, 3 Aug 2023 06:10:52 +0100 Subject: [PATCH] Add functions to set Parent Endpoint and Composition Type for an Endpoint (#28410) * Added endpointCompositionType to the EmberAfDefinedEndpoint structure to be used to hold whether an endpoint is flat or tree composed - defaults to Flat to assume previous behaviour as default * Added functions to support setting and getting composition type and also to set an endpoints parent endpoint * updated Read handler for parts list to make its else branch for Flat composition and then added a further branch to handle Tree composition * Restyled by clang-format * Fixed mistake in return type of emberAfEndpointCompositionTypeForEndpoint * Removing debug logs * Restyled by clang-format * Moved new API funciotns to chip::app namespace and removed ember naming. Made endpoint struct use a proper bitmask as it was basically using an enum in a weird way * Moved Read for Parts List to use new function naming * Restyled by clang-format * Replaced EmberAfStatus with CHIP_ERROR * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/app/clusters/descriptor/descriptor.cpp | 20 +++++- src/app/util/af-types.h | 15 ++--- src/app/util/af.h | 27 +++++++- src/app/util/attribute-storage.cpp | 74 ++++++++++++++++++++-- 4 files changed, 118 insertions(+), 18 deletions(-) diff --git a/src/app/clusters/descriptor/descriptor.cpp b/src/app/clusters/descriptor/descriptor.cpp index 95f290a0afd732..8d8b318639722e 100644 --- a/src/app/clusters/descriptor/descriptor.cpp +++ b/src/app/clusters/descriptor/descriptor.cpp @@ -76,7 +76,7 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu return CHIP_NO_ERROR; }); } - else + else if (IsFlatCompositionForEndpoint(endpoint)) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { for (uint16_t index = 0; index < emberAfEndpointCount(); index++) @@ -104,6 +104,24 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu return CHIP_NO_ERROR; }); } + else if (IsTreeCompositionForEndpoint(endpoint)) + { + err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { + for (uint16_t index = 0; index < emberAfEndpointCount(); index++) + { + if (!emberAfEndpointIndexIsEnabled(index)) + continue; + + EndpointId parentEndpointId = emberAfParentEndpointFromIndex(index); + if (parentEndpointId == endpoint) + { + ReturnErrorOnFailure(encoder.Encode(emberAfEndpointFromIndex(index))); + } + } + + return CHIP_NO_ERROR; + }); + } return err; } diff --git a/src/app/util/af-types.h b/src/app/util/af-types.h index 9c4a7ca6a5f069..20ab5fcfc0b508 100644 --- a/src/app/util/af-types.h +++ b/src/app/util/af-types.h @@ -181,14 +181,11 @@ typedef struct uint16_t endpointSize; } EmberAfEndpointType; -#ifdef DOXYGEN_SHOULD_SKIP_THIS -enum EmberAfEndpointBitmask; -#else -typedef uint8_t EmberAfEndpointBitmask; -enum -#endif -{ EMBER_AF_ENDPOINT_DISABLED = 0x00, - EMBER_AF_ENDPOINT_ENABLED = 0x01, +enum class EmberAfEndpointOptions : uint8_t +{ + isEnabled = 0x1, + isFlatComposition = 0x2, + isTreeComposition = 0x3, }; /** @@ -209,7 +206,7 @@ struct EmberAfDefinedEndpoint /** * Meta-data about the endpoint */ - EmberAfEndpointBitmask bitmask = EMBER_AF_ENDPOINT_DISABLED; + chip::BitMask bitmask; /** * Endpoint type for this endpoint. */ diff --git a/src/app/util/af.h b/src/app/util/af.h index 1ea0fa64872698..0875c09478c8d8 100644 --- a/src/app/util/af.h +++ b/src/app/util/af.h @@ -130,7 +130,7 @@ extern EmberAfDefinedEndpoint emAfEndpoints[]; #endif /** - * @brief Returns root endpoint of a composed bridged device + * @brief Returns parent endpoint for a given endpoint index */ chip::EndpointId emberAfParentEndpointFromIndex(uint16_t index); @@ -303,5 +303,30 @@ class EnabledEndpointsWithServerCluster ClusterId mClusterId; }; +/** + * @brief Sets the parent endpoint for a given endpoint + */ +CHIP_ERROR SetParentEndpointForEndpoint(EndpointId childEndpoint, EndpointId parentEndpoint); + +/** + * @brief Sets an Endpoint to use Flat Composition + */ +CHIP_ERROR SetFlatCompositionForEndpoint(EndpointId endpoint); + +/** + * @brief Sets an Endpoint to use Tree Composition + */ +CHIP_ERROR SetTreeCompositionForEndpoint(EndpointId endpoint); + +/** + * @brief Returns true is an Endpoint has flat composition + */ +bool IsFlatCompositionForEndpoint(EndpointId endpoint); + +/** + * @brief Returns true is an Endpoint has tree composition + */ +bool IsTreeCompositionForEndpoint(EndpointId endpoint); + } // namespace app } // namespace chip diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index 788723a2162bf5..118e38f78961f2 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -192,7 +192,9 @@ void emberAfEndpointConfigure() emAfEndpoints[ep].deviceTypeList = endpointDeviceTypeList(ep); emAfEndpoints[ep].endpointType = endpointTypeMacro(ep); emAfEndpoints[ep].dataVersions = currentDataVersions; - emAfEndpoints[ep].bitmask = EMBER_AF_ENDPOINT_ENABLED; + + emAfEndpoints[ep].bitmask.Set(EmberAfEndpointOptions::isEnabled); + emAfEndpoints[ep].bitmask.Set(EmberAfEndpointOptions::isFlatComposition); // Increment currentDataVersions by 1 (slot) for every server cluster // this endpoint has. @@ -271,7 +273,7 @@ EmberAfStatus emberAfSetDynamicEndpoint(uint16_t index, EndpointId id, const Emb emAfEndpoints[index].endpointType = ep; emAfEndpoints[index].dataVersions = dataVersionStorage.data(); // Start the endpoint off as disabled. - emAfEndpoints[index].bitmask = EMBER_AF_ENDPOINT_DISABLED; + emAfEndpoints[index].bitmask.Clear(EmberAfEndpointOptions::isEnabled); emAfEndpoints[index].parentEndpointId = parentEndpointId; emberAfSetDynamicEndpointCount(MAX_ENDPOINT_COUNT - FIXED_ENDPOINT_COUNT); @@ -322,7 +324,7 @@ uint16_t emberAfEndpointCount() bool emberAfEndpointIndexIsEnabled(uint16_t index) { - return (emAfEndpoints[index].bitmask & EMBER_AF_ENDPOINT_ENABLED); + return (emAfEndpoints[index].bitmask.Has(EmberAfEndpointOptions::isEnabled)); } bool emberAfIsStringAttributeType(EmberAfAttributeType attributeType) @@ -838,7 +840,7 @@ static uint16_t findIndexFromEndpoint(EndpointId endpoint, bool ignoreDisabledEn for (epi = 0; epi < emberAfEndpointCount(); epi++) { if (emAfEndpoints[epi].endpoint == endpoint && - (!ignoreDisabledEndpoints || emAfEndpoints[epi].bitmask & EMBER_AF_ENDPOINT_ENABLED)) + (!ignoreDisabledEndpoints || emAfEndpoints[epi].bitmask.Has(EmberAfEndpointOptions::isEnabled))) { return epi; } @@ -919,11 +921,11 @@ bool emberAfEndpointEnableDisable(EndpointId endpoint, bool enable) return false; } - currentlyEnabled = emAfEndpoints[index].bitmask & EMBER_AF_ENDPOINT_ENABLED; + currentlyEnabled = emAfEndpoints[index].bitmask.Has(EmberAfEndpointOptions::isEnabled); if (enable) { - emAfEndpoints[index].bitmask |= EMBER_AF_ENDPOINT_ENABLED; + emAfEndpoints[index].bitmask.Set(EmberAfEndpointOptions::isEnabled); } #if defined(EZSP_HOST) @@ -962,7 +964,7 @@ bool emberAfEndpointEnableDisable(EndpointId endpoint, bool enable) if (!enable) { - emAfEndpoints[index].bitmask &= EMBER_AF_ENDPOINT_DISABLED; + emAfEndpoints[index].bitmask.Clear(EmberAfEndpointOptions::isEnabled); } return true; @@ -1421,6 +1423,64 @@ app::AttributeAccessInterface * GetAttributeAccessOverride(EndpointId endpointId return nullptr; } + +CHIP_ERROR SetParentEndpointForEndpoint(EndpointId childEndpoint, EndpointId parentEndpoint) +{ + uint16_t childIndex = emberAfIndexFromEndpoint(childEndpoint); + uint16_t parentIndex = emberAfIndexFromEndpoint(parentEndpoint); + + if (childIndex == kEmberInvalidEndpointIndex || parentIndex == kEmberInvalidEndpointIndex) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + emAfEndpoints[childIndex].parentEndpointId = parentEndpoint; + return CHIP_NO_ERROR; +} + +CHIP_ERROR SetFlatCompositionForEndpoint(EndpointId endpoint) +{ + uint16_t index = emberAfIndexFromEndpoint(endpoint); + if (index == kEmberInvalidEndpointIndex) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + emAfEndpoints[index].bitmask.Clear(EmberAfEndpointOptions::isTreeComposition); + emAfEndpoints[index].bitmask.Set(EmberAfEndpointOptions::isFlatComposition); + return CHIP_NO_ERROR; +} + +CHIP_ERROR SetTreeCompositionForEndpoint(EndpointId endpoint) +{ + uint16_t index = emberAfIndexFromEndpoint(endpoint); + if (index == kEmberInvalidEndpointIndex) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + emAfEndpoints[index].bitmask.Clear(EmberAfEndpointOptions::isFlatComposition); + emAfEndpoints[index].bitmask.Set(EmberAfEndpointOptions::isTreeComposition); + return CHIP_NO_ERROR; +} + +bool IsFlatCompositionForEndpoint(EndpointId endpoint) +{ + uint16_t index = emberAfIndexFromEndpoint(endpoint); + if (index == kEmberInvalidEndpointIndex) + { + return false; + } + return emAfEndpoints[index].bitmask.Has(EmberAfEndpointOptions::isFlatComposition); +} + +bool IsTreeCompositionForEndpoint(EndpointId endpoint) +{ + uint16_t index = emberAfIndexFromEndpoint(endpoint); + if (index == kEmberInvalidEndpointIndex) + { + return false; + } + return emAfEndpoints[index].bitmask.Has(EmberAfEndpointOptions::isTreeComposition); +} + } // namespace app } // namespace chip