-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ember compatibility layer - split out GlobalAttributeAccessInterface …
…and the I/O buffer (#33396) * Split out ember-compatibiltiy-functions with some shareable bits. When looking to implement the ember/codegen data mode, some functionality in ember-compatibility-functions needs sharing to avoid extra copy&paste bloat: - Global attribute handling via AAI split into a separate file - Raw "data I/O" buffer split into a separate file Moved privilege-storage and implemented a few more mock ember methods. * Also update linter * Remove obsolete file * Fix odd include * Add files to Matter.xcodeproject * Update src/app/util/ember-io-storage.h Co-authored-by: Boris Zbarsky <[email protected]> * Update ember-io-storage.h Add additional comments. * Restyle --------- Co-authored-by: Andrei Litvin <[email protected]> Co-authored-by: Boris Zbarsky <[email protected]>
- Loading branch information
1 parent
b653e8e
commit 3219a5f
Showing
15 changed files
with
475 additions
and
266 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
136 changes: 136 additions & 0 deletions
136
src/app/util/ember-global-attribute-access-interface.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Copyright (c) 2021-2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
#include <app/util/ember-global-attribute-access-interface.h> | ||
|
||
#include <app/GlobalAttributes.h> | ||
#include <app/InteractionModelEngine.h> | ||
|
||
namespace chip { | ||
namespace app { | ||
namespace Compatibility { | ||
|
||
CHIP_ERROR GlobalAttributeReader::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) | ||
{ | ||
using namespace Clusters::Globals::Attributes; | ||
switch (aPath.mAttributeId) | ||
{ | ||
case AttributeList::Id: | ||
return aEncoder.EncodeList([this](const auto & encoder) { | ||
const size_t count = mCluster->attributeCount; | ||
bool addedExtraGlobals = false; | ||
for (size_t i = 0; i < count; ++i) | ||
{ | ||
AttributeId id = mCluster->attributes[i].attributeId; | ||
constexpr auto lastGlobalId = GlobalAttributesNotInMetadata[ArraySize(GlobalAttributesNotInMetadata) - 1]; | ||
#if CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE | ||
// The GlobalAttributesNotInMetadata shouldn't have any gaps in their ids here. | ||
static_assert(lastGlobalId - GlobalAttributesNotInMetadata[0] == ArraySize(GlobalAttributesNotInMetadata) - 1, | ||
"Ids in GlobalAttributesNotInMetadata not consecutive"); | ||
#else | ||
// If EventList is not supported. The GlobalAttributesNotInMetadata is missing one id here. | ||
static_assert(lastGlobalId - GlobalAttributesNotInMetadata[0] == ArraySize(GlobalAttributesNotInMetadata), | ||
"Ids in GlobalAttributesNotInMetadata not consecutive (except EventList)"); | ||
#endif // CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE | ||
if (!addedExtraGlobals && id > lastGlobalId) | ||
{ | ||
for (const auto & globalId : GlobalAttributesNotInMetadata) | ||
{ | ||
ReturnErrorOnFailure(encoder.Encode(globalId)); | ||
} | ||
addedExtraGlobals = true; | ||
} | ||
ReturnErrorOnFailure(encoder.Encode(id)); | ||
} | ||
if (!addedExtraGlobals) | ||
{ | ||
for (const auto & globalId : GlobalAttributesNotInMetadata) | ||
{ | ||
ReturnErrorOnFailure(encoder.Encode(globalId)); | ||
} | ||
} | ||
return CHIP_NO_ERROR; | ||
}); | ||
#if CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE | ||
case EventList::Id: | ||
return aEncoder.EncodeList([this](const auto & encoder) { | ||
for (size_t i = 0; i < mCluster->eventCount; ++i) | ||
{ | ||
ReturnErrorOnFailure(encoder.Encode(mCluster->eventList[i])); | ||
} | ||
return CHIP_NO_ERROR; | ||
}); | ||
#endif // CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE | ||
case AcceptedCommandList::Id: | ||
return EncodeCommandList(aPath, aEncoder, &CommandHandlerInterface::EnumerateAcceptedCommands, | ||
mCluster->acceptedCommandList); | ||
case GeneratedCommandList::Id: | ||
return EncodeCommandList(aPath, aEncoder, &CommandHandlerInterface::EnumerateGeneratedCommands, | ||
mCluster->generatedCommandList); | ||
default: | ||
// This function is only called if attributeCluster is non-null in | ||
// ReadSingleClusterData, which only happens for attributes listed in | ||
// GlobalAttributesNotInMetadata. If we reach this code, someone added | ||
// a global attribute to that list but not the above switch. | ||
VerifyOrDieWithMsg(false, DataManagement, "Unexpected global attribute: " ChipLogFormatMEI, | ||
ChipLogValueMEI(aPath.mAttributeId)); | ||
return CHIP_NO_ERROR; | ||
} | ||
} | ||
|
||
CHIP_ERROR GlobalAttributeReader::EncodeCommandList(const ConcreteClusterPath & aClusterPath, AttributeValueEncoder & aEncoder, | ||
GlobalAttributeReader::CommandListEnumerator aEnumerator, | ||
const CommandId * aClusterCommandList) | ||
{ | ||
return aEncoder.EncodeList([&](const auto & encoder) { | ||
auto * commandHandler = | ||
InteractionModelEngine::GetInstance()->FindCommandHandler(aClusterPath.mEndpointId, aClusterPath.mClusterId); | ||
if (commandHandler) | ||
{ | ||
struct Context | ||
{ | ||
decltype(encoder) & commandIdEncoder; | ||
CHIP_ERROR err; | ||
} context{ encoder, CHIP_NO_ERROR }; | ||
CHIP_ERROR err = (commandHandler->*aEnumerator)( | ||
aClusterPath, | ||
[](CommandId command, void * closure) -> Loop { | ||
auto * ctx = static_cast<Context *>(closure); | ||
ctx->err = ctx->commandIdEncoder.Encode(command); | ||
if (ctx->err != CHIP_NO_ERROR) | ||
{ | ||
return Loop::Break; | ||
} | ||
return Loop::Continue; | ||
}, | ||
&context); | ||
if (err != CHIP_ERROR_NOT_IMPLEMENTED) | ||
{ | ||
return context.err; | ||
} | ||
// Else fall through to the list in aClusterCommandList. | ||
} | ||
|
||
for (const CommandId * cmd = aClusterCommandList; cmd != nullptr && *cmd != kInvalidCommandId; cmd++) | ||
{ | ||
ReturnErrorOnFailure(encoder.Encode(*cmd)); | ||
} | ||
return CHIP_NO_ERROR; | ||
}); | ||
} | ||
|
||
} // namespace Compatibility | ||
} // namespace app | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* Copyright (c) 2021-2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
#pragma once | ||
|
||
#include <app/AttributeAccessInterface.h> | ||
#include <app/CommandHandlerInterface.h> | ||
#include <app/util/af-types.h> | ||
|
||
namespace chip { | ||
namespace app { | ||
namespace Compatibility { | ||
|
||
// This reader should never actually be registered; we do manual dispatch to it | ||
// for the one attribute it handles. | ||
class MandatoryGlobalAttributeReader : public AttributeAccessInterface | ||
{ | ||
public: | ||
MandatoryGlobalAttributeReader(const EmberAfCluster * aCluster) : | ||
AttributeAccessInterface(MakeOptional(kInvalidEndpointId), kInvalidClusterId), mCluster(aCluster) | ||
{} | ||
|
||
protected: | ||
const EmberAfCluster * mCluster; | ||
}; | ||
|
||
class GlobalAttributeReader : public MandatoryGlobalAttributeReader | ||
{ | ||
public: | ||
GlobalAttributeReader(const EmberAfCluster * aCluster) : MandatoryGlobalAttributeReader(aCluster) {} | ||
|
||
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; | ||
|
||
private: | ||
typedef CHIP_ERROR (CommandHandlerInterface::*CommandListEnumerator)(const ConcreteClusterPath & cluster, | ||
CommandHandlerInterface::CommandIdCallback callback, | ||
void * context); | ||
static CHIP_ERROR EncodeCommandList(const ConcreteClusterPath & aClusterPath, AttributeValueEncoder & aEncoder, | ||
CommandListEnumerator aEnumerator, const CommandId * aClusterCommandList); | ||
}; | ||
|
||
} // namespace Compatibility | ||
} // namespace app | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/* | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
#include <app/util/ember-io-storage.h> | ||
|
||
#include <app-common/zap-generated/attribute-type.h> | ||
#include <zap-generated/endpoint_config.h> | ||
|
||
#include <cstddef> | ||
|
||
namespace chip { | ||
namespace app { | ||
namespace Compatibility { | ||
namespace Internal { | ||
|
||
// On some apps, ATTRIBUTE_LARGEST can as small as 3, making compiler unhappy since data[kAttributeReadBufferSize] cannot hold | ||
// uint64_t. Make kAttributeReadBufferSize at least 8 so it can fit all basic types. | ||
constexpr size_t kAttributeReadBufferSize = (ATTRIBUTE_LARGEST >= 8 ? ATTRIBUTE_LARGEST : 8); | ||
uint8_t attributeIOBuffer[kAttributeReadBufferSize]; | ||
|
||
MutableByteSpan gEmberAttributeIOBufferSpan(attributeIOBuffer); | ||
|
||
EmberAfAttributeType AttributeBaseType(EmberAfAttributeType type) | ||
{ | ||
switch (type) | ||
{ | ||
case ZCL_ACTION_ID_ATTRIBUTE_TYPE: // Action Id | ||
case ZCL_FABRIC_IDX_ATTRIBUTE_TYPE: // Fabric Index | ||
case ZCL_BITMAP8_ATTRIBUTE_TYPE: // 8-bit bitmap | ||
case ZCL_ENUM8_ATTRIBUTE_TYPE: // 8-bit enumeration | ||
case ZCL_STATUS_ATTRIBUTE_TYPE: // Status Code | ||
case ZCL_PERCENT_ATTRIBUTE_TYPE: // Percentage | ||
static_assert(std::is_same<chip::Percent, uint8_t>::value, | ||
"chip::Percent is expected to be uint8_t, change this when necessary"); | ||
return ZCL_INT8U_ATTRIBUTE_TYPE; | ||
|
||
case ZCL_ENDPOINT_NO_ATTRIBUTE_TYPE: // Endpoint Number | ||
case ZCL_GROUP_ID_ATTRIBUTE_TYPE: // Group Id | ||
case ZCL_VENDOR_ID_ATTRIBUTE_TYPE: // Vendor Id | ||
case ZCL_ENUM16_ATTRIBUTE_TYPE: // 16-bit enumeration | ||
case ZCL_BITMAP16_ATTRIBUTE_TYPE: // 16-bit bitmap | ||
case ZCL_PERCENT100THS_ATTRIBUTE_TYPE: // 100ths of a percent | ||
static_assert(std::is_same<chip::EndpointId, uint16_t>::value, | ||
"chip::EndpointId is expected to be uint16_t, change this when necessary"); | ||
static_assert(std::is_same<chip::GroupId, uint16_t>::value, | ||
"chip::GroupId is expected to be uint16_t, change this when necessary"); | ||
static_assert(std::is_same<chip::Percent100ths, uint16_t>::value, | ||
"chip::Percent100ths is expected to be uint16_t, change this when necessary"); | ||
return ZCL_INT16U_ATTRIBUTE_TYPE; | ||
|
||
case ZCL_CLUSTER_ID_ATTRIBUTE_TYPE: // Cluster Id | ||
case ZCL_ATTRIB_ID_ATTRIBUTE_TYPE: // Attribute Id | ||
case ZCL_FIELD_ID_ATTRIBUTE_TYPE: // Field Id | ||
case ZCL_EVENT_ID_ATTRIBUTE_TYPE: // Event Id | ||
case ZCL_COMMAND_ID_ATTRIBUTE_TYPE: // Command Id | ||
case ZCL_TRANS_ID_ATTRIBUTE_TYPE: // Transaction Id | ||
case ZCL_DEVTYPE_ID_ATTRIBUTE_TYPE: // Device Type Id | ||
case ZCL_DATA_VER_ATTRIBUTE_TYPE: // Data Version | ||
case ZCL_BITMAP32_ATTRIBUTE_TYPE: // 32-bit bitmap | ||
case ZCL_EPOCH_S_ATTRIBUTE_TYPE: // Epoch Seconds | ||
case ZCL_ELAPSED_S_ATTRIBUTE_TYPE: // Elapsed Seconds | ||
static_assert(std::is_same<chip::ClusterId, uint32_t>::value, | ||
"chip::Cluster is expected to be uint32_t, change this when necessary"); | ||
static_assert(std::is_same<chip::AttributeId, uint32_t>::value, | ||
"chip::AttributeId is expected to be uint32_t, change this when necessary"); | ||
static_assert(std::is_same<chip::AttributeId, uint32_t>::value, | ||
"chip::AttributeId is expected to be uint32_t, change this when necessary"); | ||
static_assert(std::is_same<chip::EventId, uint32_t>::value, | ||
"chip::EventId is expected to be uint32_t, change this when necessary"); | ||
static_assert(std::is_same<chip::CommandId, uint32_t>::value, | ||
"chip::CommandId is expected to be uint32_t, change this when necessary"); | ||
static_assert(std::is_same<chip::TransactionId, uint32_t>::value, | ||
"chip::TransactionId is expected to be uint32_t, change this when necessary"); | ||
static_assert(std::is_same<chip::DeviceTypeId, uint32_t>::value, | ||
"chip::DeviceTypeId is expected to be uint32_t, change this when necessary"); | ||
static_assert(std::is_same<chip::DataVersion, uint32_t>::value, | ||
"chip::DataVersion is expected to be uint32_t, change this when necessary"); | ||
return ZCL_INT32U_ATTRIBUTE_TYPE; | ||
|
||
case ZCL_AMPERAGE_MA_ATTRIBUTE_TYPE: // Amperage milliamps | ||
case ZCL_ENERGY_MWH_ATTRIBUTE_TYPE: // Energy milliwatt-hours | ||
case ZCL_POWER_MW_ATTRIBUTE_TYPE: // Power milliwatts | ||
case ZCL_VOLTAGE_MV_ATTRIBUTE_TYPE: // Voltage millivolts | ||
return ZCL_INT64S_ATTRIBUTE_TYPE; | ||
|
||
case ZCL_EVENT_NO_ATTRIBUTE_TYPE: // Event Number | ||
case ZCL_FABRIC_ID_ATTRIBUTE_TYPE: // Fabric Id | ||
case ZCL_NODE_ID_ATTRIBUTE_TYPE: // Node Id | ||
case ZCL_BITMAP64_ATTRIBUTE_TYPE: // 64-bit bitmap | ||
case ZCL_EPOCH_US_ATTRIBUTE_TYPE: // Epoch Microseconds | ||
case ZCL_POSIX_MS_ATTRIBUTE_TYPE: // POSIX Milliseconds | ||
case ZCL_SYSTIME_MS_ATTRIBUTE_TYPE: // System time Milliseconds | ||
case ZCL_SYSTIME_US_ATTRIBUTE_TYPE: // System time Microseconds | ||
static_assert(std::is_same<chip::EventNumber, uint64_t>::value, | ||
"chip::EventNumber is expected to be uint64_t, change this when necessary"); | ||
static_assert(std::is_same<chip::FabricId, uint64_t>::value, | ||
"chip::FabricId is expected to be uint64_t, change this when necessary"); | ||
static_assert(std::is_same<chip::NodeId, uint64_t>::value, | ||
"chip::NodeId is expected to be uint64_t, change this when necessary"); | ||
return ZCL_INT64U_ATTRIBUTE_TYPE; | ||
|
||
case ZCL_TEMPERATURE_ATTRIBUTE_TYPE: // Temperature | ||
return ZCL_INT16S_ATTRIBUTE_TYPE; | ||
|
||
default: | ||
return type; | ||
} | ||
} | ||
|
||
} // namespace Internal | ||
} // namespace Compatibility | ||
} // namespace app | ||
} // namespace chip |
Oops, something went wrong.