From 9dd20161c090cde98ad57eae3076f6959d46286c Mon Sep 17 00:00:00 2001 From: Sergei Lissianoi <54454955+selissia@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:09:56 -0500 Subject: [PATCH 1/9] [CSA-CP] Cherry pick the OTA fix (CSA PR #37643) (#317) Co-authored-by: Olivier Belisle Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .../DefaultOTARequestorStorage.cpp | 23 +++++++++- .../DefaultOTARequestorStorage.h | 4 ++ .../tests/TestDefaultOTARequestorStorage.cpp | 42 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp b/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp index 2258c7af30..a06fa7db2f 100644 --- a/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp +++ b/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp @@ -59,6 +59,24 @@ CHIP_ERROR DefaultOTARequestorStorage::StoreDefaultProviders(const ProviderLocat static_cast(writer.GetLengthWritten())); } +bool DefaultOTARequestorStorage::ProviderAlreadyInList(ProviderLocationList & listProviders, ProviderLocationType provider) +{ + auto iterator = listProviders.Begin(); + + while (iterator.Next()) + { + ProviderLocationType pl = iterator.GetValue(); + + if ((pl.providerNodeID == provider.providerNodeID) && (pl.fabricIndex == provider.fabricIndex) && + (pl.endpoint == provider.endpoint)) + { + return true; + } + } + + return false; +} + CHIP_ERROR DefaultOTARequestorStorage::LoadDefaultProviders(ProviderLocationList & providers) { uint8_t buffer[kProviderListMaxSerializedSize]; @@ -77,7 +95,10 @@ CHIP_ERROR DefaultOTARequestorStorage::LoadDefaultProviders(ProviderLocationList { ProviderLocationType provider; ReturnErrorOnFailure(provider.Decode(reader)); - providers.Add(provider); + if (!ProviderAlreadyInList(providers, provider)) + { + providers.Add(provider); + } } ReturnErrorOnFailure(reader.ExitContainer(outerType)); diff --git a/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.h b/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.h index 048e8d4d09..11ccb4b3d4 100644 --- a/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.h +++ b/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.h @@ -49,6 +49,10 @@ class DefaultOTARequestorStorage : public OTARequestorStorage CHIP_ERROR ClearTargetVersion() override; private: + /** + * Check whether a provider is already present in a list of providers. + */ + bool ProviderAlreadyInList(ProviderLocationList & listProviders, ProviderLocationType provider); CHIP_ERROR Load(const char * key, MutableByteSpan & buffer); PersistentStorageDelegate * mPersistentStorage = nullptr; }; diff --git a/src/app/tests/TestDefaultOTARequestorStorage.cpp b/src/app/tests/TestDefaultOTARequestorStorage.cpp index 53ee108e73..b1086fc83c 100644 --- a/src/app/tests/TestDefaultOTARequestorStorage.cpp +++ b/src/app/tests/TestDefaultOTARequestorStorage.cpp @@ -97,6 +97,48 @@ TEST(TestDefaultOTARequestorStorage, TestDefaultProvidersEmpty) EXPECT_FALSE(providers.Begin().Next()); } +TEST(TestDefaultOTARequestorStorage, TestDefaultProvidersDuplicated) +{ + TestPersistentStorageDelegate persistentStorage; + DefaultOTARequestorStorage otaStorage; + otaStorage.Init(persistentStorage); + + const auto makeProvider = [](FabricIndex fabric, NodeId nodeId, EndpointId endpointId) { + OTARequestorStorage::ProviderLocationType provider; + provider.fabricIndex = fabric; + provider.providerNodeID = nodeId; + provider.endpoint = endpointId; + return provider; + }; + + ProviderLocationList providers = {}; + + EXPECT_EQ(CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, otaStorage.LoadDefaultProviders(providers)); + auto iterator = providers.Begin(); + EXPECT_EQ(false, iterator.Next()); + + for (uint8_t i = 0; i < CHIP_CONFIG_MAX_FABRICS; i++) + { + EXPECT_EQ(CHIP_NO_ERROR, providers.Add(makeProvider(FabricIndex(1), NodeId(0x11111111), EndpointId(1)))); + } + + EXPECT_EQ(CHIP_NO_ERROR, otaStorage.StoreDefaultProviders(providers)); + + providers = {}; + EXPECT_EQ(CHIP_NO_ERROR, otaStorage.LoadDefaultProviders(providers)); + + iterator = providers.Begin(); + + // Check provider #1 + EXPECT_EQ(true, iterator.Next()); + OTARequestorStorage::ProviderLocationType provider1 = iterator.GetValue(); + EXPECT_EQ(FabricIndex(1), provider1.fabricIndex); + EXPECT_EQ(NodeId(0x11111111), provider1.providerNodeID); + EXPECT_EQ(EndpointId(1), provider1.endpoint); + + EXPECT_EQ(false, iterator.Next()); +} + TEST(TestDefaultOTARequestorStorage, TestCurrentProviderLocation) { TestPersistentStorageDelegate persistentStorage; From fe7ade5d1afa2fa36381caf0be8f60d6eded08ab Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Mon, 10 Mar 2025 12:44:19 -0400 Subject: [PATCH 2/9] [CSA-CP][Silabs] Update matter_support remote to use new repository (#37363) (#322) --- .gitmodules | 4 +- examples/platform/silabs/BaseApplication.cpp | 2 +- examples/platform/silabs/MatterConfig.cpp | 2 +- examples/platform/silabs/SiWx917/BUILD.gn | 8 +- .../silabs/SilabsTestEventTriggerDelegate.cpp | 2 +- examples/platform/silabs/efr32/BUILD.gn | 7 +- examples/platform/silabs/provision/BUILD.gn | 15 +- .../provision/ProvisionStorageCustom.cpp | 2 +- .../provision/ProvisionStorageDefault.cpp | 4 +- .../provision/ProvisionStorageFlash.cpp | 6 +- examples/refrigerator-app/silabs/BUILD.gn | 2 +- scripts/examples/gn_silabs_example.sh | 4 +- src/platform/silabs/SiWx917/BUILD.gn | 4 +- src/platform/silabs/efr32/BLEManagerImpl.cpp | 4 +- src/platform/silabs/efr32/BUILD.gn | 5 +- .../multi-ota/OTAFactoryDataProcessor.h | 4 +- .../silabs/provision/AttestationKey.h | 56 ---- src/platform/silabs/provision/BUILD.gn | 38 --- .../silabs/provision/ProvisionChannel.h | 44 --- .../silabs/provision/ProvisionEncoder.h | 229 ------------- .../silabs/provision/ProvisionManager.h | 54 --- .../silabs/provision/ProvisionProtocol.h | 101 ------ .../silabs/provision/ProvisionStorage.h | 312 ------------------ .../provision/ProvisionStorageGeneric.h | 47 --- src/platform/silabs/provision/args.gni | 19 -- src/platform/silabs/wifi/BUILD.gn | 2 +- src/platform/silabs/wifi/rs911x/rs9117.gni | 2 +- src/test_driver/efr32/BUILD.gn | 7 +- src/test_driver/efr32/src/main.cpp | 3 +- .../openthread/platforms/efr32/BUILD.gn | 6 +- third_party/silabs/BUILD.gn | 4 +- third_party/silabs/SiWx917_sdk.gni | 36 +- third_party/silabs/efr32_sdk.gni | 55 ++- third_party/silabs/matter_support | 2 +- 34 files changed, 101 insertions(+), 991 deletions(-) delete mode 100644 src/platform/silabs/provision/AttestationKey.h delete mode 100644 src/platform/silabs/provision/BUILD.gn delete mode 100644 src/platform/silabs/provision/ProvisionChannel.h delete mode 100644 src/platform/silabs/provision/ProvisionEncoder.h delete mode 100644 src/platform/silabs/provision/ProvisionManager.h delete mode 100644 src/platform/silabs/provision/ProvisionProtocol.h delete mode 100644 src/platform/silabs/provision/ProvisionStorage.h delete mode 100644 src/platform/silabs/provision/ProvisionStorageGeneric.h delete mode 100644 src/platform/silabs/provision/args.gni diff --git a/.gitmodules b/.gitmodules index c2b9a95a5e..b90c3fa957 100644 --- a/.gitmodules +++ b/.gitmodules @@ -207,8 +207,8 @@ platforms = mw320 [submodule "third_party/silabs/matter_support"] path = third_party/silabs/matter_support - url = https://github.com/SiliconLabs/sdk_support.git - branch = main + url = https://github.com/SiliconLabsSoftware/matter_support.git + branch = release_2.5-1.4 platforms = silabs,silabs_docker [submodule "third_party/silabs/simplicity_sdk"] path = third_party/silabs/simplicity_sdk diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index c840e4c5e6..3ab8bcfd4b 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -44,10 +44,10 @@ #endif // ENABLE_CHIP_SHELL #endif // CHIP_CONFIG_ENABLE_ICD_SERVER -#include #include #include #include +#include #include #include #include diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index 4c5d0fa53b..9ef140989e 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -63,9 +63,9 @@ static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeystore; #endif -#include #include #include +#include #ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED #include "SilabsTestEventTriggerDelegate.h" // nogncheck diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 9d5ca9ff66..88fe68a1e7 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -19,11 +19,15 @@ import("${chip_root}/examples/platform/silabs/args.gni") import("${chip_root}/src/app/icd/icd.gni") import("${chip_root}/src/lib/lib.gni") import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/silabs/provision/args.gni") import("${chip_root}/src/platform/silabs/wifi/args.gni") import("${chip_root}/third_party/silabs/silabs_board.gni") import("${silabs_sdk_build_root}/SiWx917_sdk.gni") +import("${matter_support_root}/provision/args.gni") # Seperate import since the + # matter_support_root is + # defined in the + # ef32_sdk.gni + declare_args() { enable_heap_monitoring = false @@ -69,7 +73,7 @@ source_set("test-event-trigger") { "${silabs_common_plat_dir}/SilabsTestEventTriggerDelegate.h", ] - deps = [ "${sl_provision_root}:provision-headers" ] + deps = [ "${sl_provision_root}:headers" ] public_configs = [ ":test-event-trigger-config" ] public_deps = [ "${chip_root}/src/app:test-event-trigger", diff --git a/examples/platform/silabs/SilabsTestEventTriggerDelegate.cpp b/examples/platform/silabs/SilabsTestEventTriggerDelegate.cpp index 78aadb1bd0..d443eb0f12 100644 --- a/examples/platform/silabs/SilabsTestEventTriggerDelegate.cpp +++ b/examples/platform/silabs/SilabsTestEventTriggerDelegate.cpp @@ -17,7 +17,7 @@ */ #include "SilabsTestEventTriggerDelegate.h" -#include +#include #include using namespace ::chip::DeviceLayer; diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index 98a44d12b1..ff141b8c38 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -18,11 +18,14 @@ import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") import("${chip_root}/src/app/icd/icd.gni") import("${chip_root}/src/lib/lib.gni") import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/silabs/provision/args.gni") import("${chip_root}/src/tracing/tracing_args.gni") import("${silabs_sdk_build_root}/efr32_sdk.gni") import("${silabs_sdk_build_root}/silabs_board.gni") +import("${matter_support_root}/provision/args.gni") # Seperate import since the + # matter_support_root is + # defined in the + # ef32_sdk.gni declare_args() { enable_heap_monitoring = false @@ -73,7 +76,7 @@ source_set("test-event-trigger") { "${silabs_common_plat_dir}/SilabsTestEventTriggerDelegate.h", ] - deps = [ "${sl_provision_root}:provision-headers" ] + deps = [ "${sl_provision_root}:headers" ] public_configs = [ ":test-event-trigger-config" ] public_deps = [ "${chip_root}/src/app:test-event-trigger", diff --git a/examples/platform/silabs/provision/BUILD.gn b/examples/platform/silabs/provision/BUILD.gn index 1ab4744a2e..79931e3c60 100644 --- a/examples/platform/silabs/provision/BUILD.gn +++ b/examples/platform/silabs/provision/BUILD.gn @@ -14,7 +14,6 @@ import("//build_overrides/chip.gni") import("//build_overrides/efr32_sdk.gni") -import("${chip_root}/src/platform/silabs/provision/args.gni") import("${silabs_sdk_build_root}/silabs_board.gni") if (wifi_soc) { @@ -23,6 +22,8 @@ if (wifi_soc) { import("${silabs_sdk_build_root}/efr32_sdk.gni") } +# Seperate import since the matter_support_root is defined in the ef32_sdk.gni / SiWx917_sdk.gni +import("${matter_support_root}/provision/args.gni") source_set("storage") { sources = [ "ProvisionStorageCustom.cpp" ] @@ -34,22 +35,22 @@ source_set("storage") { if (wifi_soc) { if (sl_si91x_crypto_flavor == "psa") { - libs = - [ "${sdk_support_root}/matter/provision/lib/libProvisionPSA_si917.a" ] + libs = [ "${sl_provision_root}/libs/libProvisionPSA_si917.a" ] } else { - libs = [ "${sdk_support_root}/matter/provision/lib/libProvision_si917.a" ] + libs = [ "${sl_provision_root}/libs/libProvision_si917.a" ] } } else { if (use_provision_flash_storage) { - libs = [ "${sdk_support_root}/matter/provision/lib/libProvisionFlash_${silabs_family}.a" ] + libs = + [ "${sl_provision_root}/libs/libProvisionFlash_${silabs_family}.a" ] } else { - libs = [ "${sdk_support_root}/matter/provision/lib/libProvision_${silabs_family}.a" ] + libs = [ "${sl_provision_root}/libs/libProvision_${silabs_family}.a" ] } } deps = [ "${chip_root}/src/lib" ] - public_deps = [ "${sl_provision_root}:provision-headers" ] + public_deps = [ "${sl_provision_root}:headers" ] if (sl_enable_test_event_trigger) { # Temporary workaround since we have duplicated configurations diff --git a/examples/platform/silabs/provision/ProvisionStorageCustom.cpp b/examples/platform/silabs/provision/ProvisionStorageCustom.cpp index 1c069fe096..22f3a75a19 100644 --- a/examples/platform/silabs/provision/ProvisionStorageCustom.cpp +++ b/examples/platform/silabs/provision/ProvisionStorageCustom.cpp @@ -15,8 +15,8 @@ * limitations under the License. */ #include +#include #include -#include #include namespace chip { diff --git a/examples/platform/silabs/provision/ProvisionStorageDefault.cpp b/examples/platform/silabs/provision/ProvisionStorageDefault.cpp index c1cc2cc335..f5d838d5bf 100644 --- a/examples/platform/silabs/provision/ProvisionStorageDefault.cpp +++ b/examples/platform/silabs/provision/ProvisionStorageDefault.cpp @@ -14,9 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "AttestationKey.h" -#include "ProvisionStorage.h" #include +#include +#include #include #include #include diff --git a/examples/platform/silabs/provision/ProvisionStorageFlash.cpp b/examples/platform/silabs/provision/ProvisionStorageFlash.cpp index 560f952aa7..047985a2ac 100644 --- a/examples/platform/silabs/provision/ProvisionStorageFlash.cpp +++ b/examples/platform/silabs/provision/ProvisionStorageFlash.cpp @@ -14,11 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "AttestationKey.h" -#include "ProvisionEncoder.h" -#include "ProvisionStorage.h" #include #include +#include +#include +#include #include #include #include diff --git a/examples/refrigerator-app/silabs/BUILD.gn b/examples/refrigerator-app/silabs/BUILD.gn index d902bb9e86..29ab32fc39 100644 --- a/examples/refrigerator-app/silabs/BUILD.gn +++ b/examples/refrigerator-app/silabs/BUILD.gn @@ -154,7 +154,7 @@ silabs_executable("refrigerator_app") { "${efr32_sdk_root}/platform/driver/i2cspm/src/sl_i2cspm.c", "${efr32_sdk_root}/platform/emlib/src/em_i2c.c", "${examples_common_plat_dir}/TemperatureSensor.cpp", - "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_i2cspm_init.c", + "${matter_support_root}/board-support/efr32/${silabs_family}/${silabs_board}/autogen/sl_i2cspm_init.c", ] } diff --git a/scripts/examples/gn_silabs_example.sh b/scripts/examples/gn_silabs_example.sh index 44f609a588..98dd56d767 100755 --- a/scripts/examples/gn_silabs_example.sh +++ b/scripts/examples/gn_silabs_example.sh @@ -118,7 +118,7 @@ if [ "$#" == "0" ]; then (default: /third_party/silabs/slc_gen//) sl_pre_gen_path Allow users to define a path to pre-generated board files - (default: /third_party/silabs/matter_support/matter///) + (default: third_party/silabs/matter_support/board-support///) sl_matter_version Use provided software version at build time sl_matter_version_str @@ -372,7 +372,7 @@ else fi # search bootloader directory for the respective bootloaders for the input board - bootloaderFiles=("$(find "$MATTER_ROOT/third_party/silabs/matter_support/matter/efr32/bootloader_binaries/" -maxdepth 1 -name "*$SILABS_BOARD*" | tr '\n' ' ')") + bootloaderFiles=("$(find "$MATTER_ROOT/third_party/silabs/matter_support/board-support/efr32/bootloader_binaries/" -maxdepth 1 -name "*$SILABS_BOARD*" | tr '\n' ' ')") if [ "${#bootloaderFiles[@]}" -gt 1 ]; then for i in "${!bootloaderFiles[@]}"; do diff --git a/src/platform/silabs/SiWx917/BUILD.gn b/src/platform/silabs/SiWx917/BUILD.gn index bca3755f1d..66e464b0b2 100644 --- a/src/platform/silabs/SiWx917/BUILD.gn +++ b/src/platform/silabs/SiWx917/BUILD.gn @@ -18,10 +18,10 @@ import("${chip_root}/src/platform/device.gni") import("${chip_root}/build/chip/buildconfig_header.gni") import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/platform/silabs/provision/args.gni") import("${chip_root}/src/platform/silabs/wifi/args.gni") import("${chip_root}/third_party/silabs/SiWx917_sdk.gni") import("${chip_root}/third_party/silabs/silabs_board.gni") +import("${matter_support_root}/provision/args.gni") silabs_platform_dir = "${chip_root}/src/platform/silabs" @@ -90,7 +90,7 @@ static_library("SiWx917") { ] deps = [ "${chip_root}/src/platform/logging:headers", - "${sl_provision_root}:provision-headers", + "${sl_provision_root}:headers", ] # Add platform crypto implementation diff --git a/src/platform/silabs/efr32/BLEManagerImpl.cpp b/src/platform/silabs/efr32/BLEManagerImpl.cpp index bc63ca1358..d3603935a9 100644 --- a/src/platform/silabs/efr32/BLEManagerImpl.cpp +++ b/src/platform/silabs/efr32/BLEManagerImpl.cpp @@ -52,8 +52,8 @@ extern "C" { #include #endif -#include -#include +#include +#include using namespace ::chip; using namespace ::chip::Ble; diff --git a/src/platform/silabs/efr32/BUILD.gn b/src/platform/silabs/efr32/BUILD.gn index 3ccd4ad3d6..ed9e68afb9 100644 --- a/src/platform/silabs/efr32/BUILD.gn +++ b/src/platform/silabs/efr32/BUILD.gn @@ -17,10 +17,10 @@ import("//build_overrides/chip.gni") import("${chip_root}/build/chip/buildconfig_header.gni") import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/silabs/provision/args.gni") import("${chip_root}/src/tracing/tracing_args.gni") import("${chip_root}/third_party/silabs/efr32_sdk.gni") import("${chip_root}/third_party/silabs/silabs_board.gni") +import("${matter_support_root}/provision/args.gni") assert(chip_device_platform == "efr32") @@ -116,9 +116,10 @@ static_library("efr32") { "${chip_root}/src/platform:platform_base", "${chip_root}/src/platform/logging:headers", ] + deps = [ "${chip_root}/src/tracing/silabs:silabs_tracing", - "${sl_provision_root}:provision-headers", + "${sl_provision_root}:headers", ] public_configs = [] diff --git a/src/platform/silabs/multi-ota/OTAFactoryDataProcessor.h b/src/platform/silabs/multi-ota/OTAFactoryDataProcessor.h index da325bbba1..dfafa66108 100644 --- a/src/platform/silabs/multi-ota/OTAFactoryDataProcessor.h +++ b/src/platform/silabs/multi-ota/OTAFactoryDataProcessor.h @@ -18,8 +18,8 @@ #pragma once -#include -#include +#include +#include #include #include #include diff --git a/src/platform/silabs/provision/AttestationKey.h b/src/platform/silabs/provision/AttestationKey.h deleted file mode 100644 index f08755ac86..0000000000 --- a/src/platform/silabs/provision/AttestationKey.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { -namespace Provision { - -static constexpr uint32_t kCreds_KeyId_Default = 2; //(PSA_KEY_ID_USER_MIN + 1); - -class AttestationKey -{ -public: - AttestationKey(uint32_t id = 0) { mId = (id > 0) ? id : kCreds_KeyId_Default; } - ~AttestationKey() = default; - - uint32_t GetId() { return mId; } - CHIP_ERROR Import(const uint8_t * asn1, size_t size); - CHIP_ERROR Export(uint8_t * asn1, size_t max, size_t & size); - CHIP_ERROR GenerateCSR(uint16_t vid, uint16_t pid, const CharSpan & cn, MutableCharSpan & csr); - CHIP_ERROR SignMessage(const ByteSpan & message, MutableByteSpan & out_span); - -#if (defined(SLI_SI91X_MCU_INTERFACE) && SLI_SI91X_MCU_INTERFACE) - static CHIP_ERROR Unwrap(const uint8_t * asn1, size_t size, MutableByteSpan & private_key); - static CHIP_ERROR SignMessageWithKey(const uint8_t * private_key, const ByteSpan & message, MutableByteSpan & out_span); -#endif // SLI_SI91X_MCU_INTERFACE - -protected: - uint32_t mId = 0; -}; - -} // namespace Provision -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/provision/BUILD.gn b/src/platform/silabs/provision/BUILD.gn deleted file mode 100644 index 7ae41c0515..0000000000 --- a/src/platform/silabs/provision/BUILD.gn +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2020 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. - -import("//build_overrides/chip.gni") -import("//build_overrides/efr32_sdk.gni") -import("${silabs_sdk_build_root}/silabs_board.gni") - -config("provision-config") { - include_dirs = [ "." ] - - defines = [ "CHIP_DEVICE_CONFIG_ENABLE_EXAMPLE_CREDENTIALS=1" ] - if (use_provision_channel) { - defines += [ "SL_MATTER_PROVISION_CHANNEL_ENABLED=1" ] - } -} - -source_set("provision-headers") { - sources = [ - "AttestationKey.h", - "ProvisionChannel.h", - "ProvisionEncoder.h", - "ProvisionManager.h", - "ProvisionProtocol.h", - "ProvisionStorage.h", - ] - public_configs = [ ":provision-config" ] -} diff --git a/src/platform/silabs/provision/ProvisionChannel.h b/src/platform/silabs/provision/ProvisionChannel.h deleted file mode 100644 index a15b4364a8..0000000000 --- a/src/platform/silabs/provision/ProvisionChannel.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ -#pragma once - -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { -namespace Provision { - -class Channel -{ -public: - Channel() = default; - ~Channel() = default; - - CHIP_ERROR Init(); - CHIP_ERROR Read(uint8_t * buffer, size_t buffer_length, size_t & bytes_read); - CHIP_ERROR Write(const uint8_t * buffer, size_t buffer_length); - - static CHIP_ERROR Update(uint16_t handle); -}; - -} // namespace Provision -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/provision/ProvisionEncoder.h b/src/platform/silabs/provision/ProvisionEncoder.h deleted file mode 100644 index 74b96fae78..0000000000 --- a/src/platform/silabs/provision/ProvisionEncoder.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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. - */ -#pragma once - -#include -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { -namespace Provision { -namespace Encoding { - -/* - Generic buffer used to hold incoming and outgoing data. - The "in" pointer marks the next address to be written. - The "out" pointer marks the next address to be read. - When "out" reaches "in", all incoming data has been read. - "Size" is the total amount of bytes written, including the part already read. - "Left" is the number of bytes available for reading. - "Offset" is the number of bytes read. - "Spare" is the number of bytes available for writing. - "Limit" it the total number of bytes allocated (size + spare). -begin out in end - |---------------v---------------v----------------| - |.....offset....|......left.....|.....spare......| - |..............size.............| - |......................limit.....................| -*/ - -struct Buffer -{ - Buffer(uint8_t * ptr, size_t size, bool at_end = false) { Init(ptr, size, at_end); } - - void Init(uint8_t * ptr, size_t size, bool at_end = false) - { - Finish(); - if (nullptr == ptr) - { - ptr = new uint8_t[size]; - allocated = true; - } - this->begin = ptr; - this->end = ptr + size; - this->in = at_end ? end : begin; - this->out = ptr; - } - void Finish() - { - if (this->begin && allocated) - { - delete[] this->begin; - } - this->begin = this->end = this->in = this->out = nullptr; - } - - /** Reset the pointers to initial position. Zero write, zero read. */ - void Clear() { this->in = this->out = this->begin; } - /** @return Total size allocated for the buffer. */ - size_t Limit() { return (this->end > this->begin) ? (this->end - this->begin) : 0; } - /** @return Number of bytes written. */ - size_t Size() { return (this->in > this->begin) ? (this->in - this->begin) : 0; } - /** @return Number of bytes read. */ - size_t Offset() { return (this->out > this->begin) ? (this->out - this->begin) : 0; } - /** @return Number of bytes available for reading. */ - size_t Left() { return this->Size() - this->Offset(); } - /** @return Number of bytes available for writing. */ - size_t Spare() { return this->Limit() - this->Size(); } - - CHIP_ERROR Add(uint8_t in); - CHIP_ERROR Add(uint16_t in); - CHIP_ERROR Add(uint32_t in); - CHIP_ERROR Add(int32_t in); - CHIP_ERROR Add(const uint8_t * in, size_t size); - CHIP_ERROR Add(Buffer & from, size_t size); - CHIP_ERROR Get(uint8_t & out); - CHIP_ERROR Get(uint16_t & out); - CHIP_ERROR Get(uint32_t & out); - CHIP_ERROR Get(uint8_t * out, size_t size); - CHIP_ERROR Get(Buffer & into, size_t size); - - uint8_t * begin = nullptr; - uint8_t * end = nullptr; - uint8_t * in = nullptr; - uint8_t * out = nullptr; - bool allocated = false; -}; - -//------------------------------------------------------------------------------ -// Version 1 -//------------------------------------------------------------------------------ -#ifdef SILABS_PROVISION_PROTOCOL_V1 - -namespace Version1 { - -enum Types : uint8_t -{ - Type_None = 0x00, - Type_Int8u = 0x01, - Type_Int16u = 0x02, - Type_Int32u = 0x03, - Type_Array = 0x04, -}; - -CHIP_ERROR Encode(Buffer & arg, uint8_t in); -CHIP_ERROR Encode(Buffer & arg, uint16_t in); -CHIP_ERROR Encode(Buffer & arg, int32_t in); -CHIP_ERROR Encode(Buffer & arg, uint32_t in); -CHIP_ERROR Encode(Buffer & arg, const uint8_t * in, size_t size); -CHIP_ERROR Encode(Buffer & arg, const char * in); - -CHIP_ERROR Decode(Buffer & arg, uint8_t & out); -CHIP_ERROR Decode(Buffer & arg, uint16_t & out); -CHIP_ERROR Decode(Buffer & arg, uint32_t & out); -CHIP_ERROR Decode(Buffer & arg, uint8_t * out, size_t limit, size_t & size); -CHIP_ERROR Decode(Buffer & arg, char * out, size_t limit, size_t & size); - -namespace Legacy { -CHIP_ERROR DecodeInt8u(Encoding::Buffer & in, uint8_t & out); -CHIP_ERROR DecodeInt16u(Encoding::Buffer & in, uint16_t & out); -CHIP_ERROR DecodeInt32u(Encoding::Buffer & in, uint32_t & out); -} // namespace Legacy - -} // namespace Version1 - -#endif // SILABS_PROVISION_PROTOCOL_V1 - -//------------------------------------------------------------------------------ -// Version 2 -//------------------------------------------------------------------------------ - -namespace Version2 { - -enum Types : uint8_t -{ - Type_Binary = 0x00, - Type_Int8u = 0x01, - Type_Int16u = 0x02, - Type_Int32u = 0x03, - Type_Int64u = 0x04, - Type_String = 0x08, - Type_Int8s = 0x09, - Type_Int16s = 0x0a, - Type_Int32s = 0x0b, - Type_Int64s = 0x0c, -}; - -union Value -{ - uint8_t u8; - uint16_t u16; - uint32_t u32; - uint32_t u64; - uint8_t * b; -}; - -struct Argument : public Buffer -{ - enum States : uint8_t - { - State_Flags = 1, - State_Size = 3, - State_Data = 4, - State_Ready = 5, - }; - - Argument(uint8_t * ptr = nullptr, size_t size = 0) : Buffer(ptr, size) { Reset(); } - - void Reset() - { - this->Clear(); - this->state = State_Flags; - this->id = 0; - this->type = 0; - this->size = 0; - this->size_len = 0; - this->encoded_size = 0; - this->is_null = false; - this->is_binary = false; - this->is_known = false; - this->feedback = false; - this->offset = 0; - memset(&this->value, 0x00, sizeof(Value)); - } - - States state = State_Flags; - uint16_t id = 0; - uint8_t type = 0; - size_t size = 0; - uint8_t size_len = 0; - size_t encoded_size = 0; - bool is_null = false; - bool is_binary = false; - bool is_known = false; - bool feedback = false; - size_t offset = 0; - Value value; -}; - -CHIP_ERROR Encode(uint16_t id, uint8_t * value, Buffer & out); -CHIP_ERROR Encode(uint16_t id, uint16_t * value, Buffer & out); -CHIP_ERROR Encode(uint16_t id, uint32_t * value, Buffer & out); -CHIP_ERROR Encode(uint16_t id, const uint8_t * value, size_t size, Buffer & out); -CHIP_ERROR Decode(Buffer & in, Argument & arg); -CHIP_ERROR Find(Buffer & in, uint16_t id, Argument & arg); - -} // namespace Version2 - -} // namespace Encoding -} // namespace Provision -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/provision/ProvisionManager.h b/src/platform/silabs/provision/ProvisionManager.h deleted file mode 100644 index 16e4592ce1..0000000000 --- a/src/platform/silabs/provision/ProvisionManager.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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. - */ -#pragma once - -#include "ProvisionChannel.h" -#include "ProvisionProtocol.h" -#include "ProvisionStorage.h" -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { -namespace Provision { - -class Manager -{ -public: - CHIP_ERROR Init(); - bool Step(); - bool IsProvisionRequired(); - CHIP_ERROR SetProvisionRequired(bool required); - Storage & GetStorage() { return mStore; } - static Manager & GetInstance(); - -private: - bool ProcessCommand(ByteSpan & request, MutableByteSpan & response); - - Storage mStore; - Channel mChannel; -#ifdef SILABS_PROVISION_PROTOCOL_V1 - Protocol1 mProtocol1; -#endif - Protocol2 mProtocol2; - bool mProvisionRequested = true; -}; - -} // namespace Provision -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/provision/ProvisionProtocol.h b/src/platform/silabs/provision/ProvisionProtocol.h deleted file mode 100644 index af3df4281a..0000000000 --- a/src/platform/silabs/provision/ProvisionProtocol.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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. - */ -#pragma once - -#include "ProvisionEncoder.h" -#include "ProvisionStorage.h" -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { -namespace Provision { - -//------------------------------------------------------------------------------ -// Common -//------------------------------------------------------------------------------ - -class Protocol -{ -public: - /** - * Must hold the header plus complete argument value - */ - virtual ~Protocol() = default; - virtual bool Execute(Storage * store, ByteSpan & request, MutableByteSpan & response) = 0; -}; - -//------------------------------------------------------------------------------ -// Version 1 -//------------------------------------------------------------------------------ -#ifdef SILABS_PROVISION_PROTOCOL_V1 - -class Protocol1 : public Protocol -{ -public: - static constexpr size_t kVersion = 1; - - virtual bool Execute(Storage * store, ByteSpan & request, MutableByteSpan & response); - -private: - CHIP_ERROR Init(Storage * store, Encoding::Buffer & in, Encoding::Buffer & out); - CHIP_ERROR GenerateCSR(Storage * store, Encoding::Buffer & in, Encoding::Buffer & out); - CHIP_ERROR Import(Storage * store, Encoding::Buffer & in, Encoding::Buffer & out); - CHIP_ERROR Setup(Storage * store, Encoding::Buffer & in, Encoding::Buffer & out); - CHIP_ERROR Read(Storage * store, Encoding::Buffer & in, Encoding::Buffer & out); -}; - -#endif // SILABS_PROVISION_PROTOCOL_V1 - -//------------------------------------------------------------------------------ -// Version 2 -//------------------------------------------------------------------------------ - -class Protocol2 : public Protocol -{ -public: - static constexpr uint8_t kVersion = 2; - // Command flags - static constexpr uint16_t kResponseFlag = 0x80; - // Payload flags - static constexpr uint16_t kCustomIdMin = 0x0000; - static constexpr uint16_t kCustomIdMax = 0x00ff; - static constexpr uint16_t kKnownIdMin = 0x0100; - static constexpr uint16_t kKnownIdMax = 0x01ff; - static constexpr uint16_t kIdMask = 0x01ff; - static constexpr uint16_t kWellKnownMask = 0x0100; - static constexpr uint16_t kSizeBit = 10; - static constexpr uint16_t kSizeMask = 0x0c00; - static constexpr uint16_t kFeedbackMask = 0x0200; - static constexpr uint16_t kTypeBit = 12; - static constexpr uint16_t kTypeMask = 0xf000; - // Limits - static constexpr size_t kPackageSizeMax = 128; - static constexpr size_t kChecksumSize = 2; - static constexpr size_t kRequestHeaderSize = 4; - static constexpr size_t kResponseHeaderSize = 8; - static_assert(kPackageSizeMax > (kResponseHeaderSize + kChecksumSize)); - - virtual bool Execute(Storage * store, ByteSpan & request, MutableByteSpan & response); -}; - -} // namespace Provision -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/provision/ProvisionStorage.h b/src/platform/silabs/provision/ProvisionStorage.h deleted file mode 100644 index c710f8cb09..0000000000 --- a/src/platform/silabs/provision/ProvisionStorage.h +++ /dev/null @@ -1,312 +0,0 @@ -/* - * 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. - */ -#pragma once - -#include "ProvisionStorageGeneric.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { -namespace Provision { - -namespace Parameters { - -enum ID : uint16_t -{ - // Internal, - kFlashAddress = 0x0101, - kFlashSize = 0x0102, - kFlashPageSize = 0x0103, - kCredsAddress = 0x0104, - kCsrFile = 0x0105, - // Options, - kVersion = 0x0111, - kAction = 0x0112, - kExtra = 0x0113, - kStop = 0x0114, - kParamsPath = 0x0121, - kInputsPath = 0x0122, - kOutputPath = 0x0123, - kTemporaryDir = 0x0124, - kTargetDevice = 0x0131, - kChannel = 0x0132, - kGenerateCreds = 0x0133, - kCsrMode = 0x0134, - kGeneratorFW = 0x0135, - kProductionFW = 0x0136, - kCertToolPath = 0x0137, - kPylinkLib = 0x013a, - kBufferSize = 0x013b, - // Instance Info, - kSerialNumber = 0x0141, - kVendorId = 0x0142, - kVendorName = 0x0143, - kProductId = 0x0144, - kProductName = 0x0145, - kProductLabel = 0x0146, - kProductUrl = 0x0147, - kPartNumber = 0x0148, - kHwVersion = 0x0151, - kHwVersionStr = 0x0152, - kManufacturingDate = 0x0153, - kPersistentUniqueId = 0x0154, - // Commissionable Data, - kDiscriminator = 0x0161, - kSpake2pPasscode = 0x0162, - kSpake2pIterations = 0x0163, - kSpake2pSalt = 0x0164, - kSpake2pVerifier = 0x0165, - kSetupPayload = 0x0166, - kCommissioningFlow = 0x0167, - kRendezvousFlags = 0x0168, - // Attestation Credentials, - kFirmwareInfo = 0x0181, - kCertification = 0x0182, - kCdCert = 0x0183, - kCdKey = 0x0184, - kPaaCert = 0x0191, - kPaaKey = 0x0192, - kPaiCert = 0x0193, - kPaiKey = 0x0194, - kDacCert = 0x0195, - kDacKey = 0x0196, - kKeyId = 0x0197, - kKeyPass = 0x0198, - kPKCS12 = 0x0199, - kCommonName = 0x01a1, - kOtaTlvEncryptionKey = 0x01a2, -}; - -} // namespace Parameters - -struct CustomStorage : public GenericStorage -{ - CHIP_ERROR Set(uint16_t id, const uint8_t * value) override; - CHIP_ERROR Get(uint16_t id, uint8_t & value) override; - CHIP_ERROR Set(uint16_t id, const uint16_t * value) override; - CHIP_ERROR Get(uint16_t id, uint16_t & value) override; - CHIP_ERROR Set(uint16_t id, const uint32_t * value) override; - CHIP_ERROR Get(uint16_t id, uint32_t & value) override; - CHIP_ERROR Set(uint16_t id, const uint64_t * value) override; - CHIP_ERROR Get(uint16_t id, uint64_t & value) override; - CHIP_ERROR Get(uint16_t id, uint8_t * value, size_t max_size, size_t & size) override; - CHIP_ERROR Set(uint16_t id, const uint8_t * value, size_t size) override; -}; - -namespace { -constexpr size_t kVersionFieldLengthInBits = 3; -constexpr size_t kVendorIDFieldLengthInBits = 16; -constexpr size_t kProductIDFieldLengthInBits = 16; -constexpr size_t kCommissioningFlowFieldLengthInBits = 2; -constexpr size_t kRendezvousInfoFieldLengthInBits = 8; -constexpr size_t kPayloadDiscriminatorFieldLengthInBits = 12; -constexpr size_t kSetupPINCodeFieldLengthInBits = 27; -constexpr size_t kPaddingFieldLengthInBits = 4; -} // namespace - -struct Storage : public GenericStorage, - public chip::DeviceLayer::DeviceInstanceInfoProvider, - public chip::DeviceLayer::CommissionableDataProvider, - public chip::Credentials::DeviceAttestationCredentialsProvider -{ - static constexpr size_t kArgumentSizeMax = 512; - static constexpr size_t kVersionLengthMax = 16; - static constexpr size_t kSerialNumberLengthMax = 32; - static constexpr size_t kVendorNameLengthMax = 32; - static constexpr size_t kProductNameLengthMax = 32; - static constexpr size_t kProductLabelLengthMax = 32; - static constexpr size_t kProductUrlLengthMax = 32; - static constexpr size_t kPartNumberLengthMax = 32; - static constexpr size_t kHardwareVersionStrLengthMax = 32; - static constexpr size_t kManufacturingDateLengthMax = 11; // yyyy-mm-dd + \0 - static constexpr size_t kPersistentUniqueIdMaxLength = 16; - static constexpr size_t kSpake2pVerifierB64LengthMax = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1; - static constexpr size_t kSpake2pSaltB64LengthMax = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1; - static constexpr size_t kFirmwareInfoSizeMax = 32; - static constexpr size_t kCertificationSizeMax = 350; - static constexpr size_t kDeviceAttestationKeySizeMax = 128; - static constexpr size_t kSetupPayloadSizeMax = 32; - static constexpr size_t kCsrLengthMax = 512; - static constexpr size_t kCommonNameMax = 128; - static constexpr size_t kTotalPayloadDataSizeInBits = - (kVersionFieldLengthInBits + kVendorIDFieldLengthInBits + kProductIDFieldLengthInBits + - kCommissioningFlowFieldLengthInBits + kRendezvousInfoFieldLengthInBits + kPayloadDiscriminatorFieldLengthInBits + - kSetupPINCodeFieldLengthInBits + kPaddingFieldLengthInBits); - static constexpr size_t kTotalPayloadDataSize = kTotalPayloadDataSizeInBits / 8; - -public: - friend class Manager; - friend class Protocol1; - friend class Command; - friend class CsrCommand; - friend class ReadCommand; - friend class WriteCommand; - - // - // Initialization - // - - CHIP_ERROR Initialize(uint32_t flash_addr = 0, uint32_t flash_size = 0); - CHIP_ERROR Commit(); - - // - // Generic Interface - // - - CHIP_ERROR Get(uint16_t id, uint8_t & value) override; - CHIP_ERROR Get(uint16_t id, uint16_t & value) override; - CHIP_ERROR Get(uint16_t id, uint32_t & value) override; - CHIP_ERROR Get(uint16_t id, uint64_t & value) override; - CHIP_ERROR Get(uint16_t id, uint8_t * value, size_t max_size, size_t & size) override; - - // - // DeviceInstanceInfoProvider - // - - CHIP_ERROR GetSerialNumber(char * value, size_t max); - CHIP_ERROR GetVendorId(uint16_t & value); - CHIP_ERROR GetVendorName(char * value, size_t max); - CHIP_ERROR GetProductId(uint16_t & productId); - CHIP_ERROR GetProductName(char * value, size_t max); - CHIP_ERROR GetProductLabel(char * value, size_t max); - CHIP_ERROR GetProductURL(char * value, size_t max); - CHIP_ERROR GetPartNumber(char * value, size_t max); - CHIP_ERROR GetHardwareVersion(uint16_t & value); - CHIP_ERROR GetHardwareVersionString(char * value, size_t max); - CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day); - CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & value); - - // - // CommissionableDataProvider - // - - CHIP_ERROR GetSetupDiscriminator(uint16_t & value); - CHIP_ERROR GetSpake2pIterationCount(uint32_t & value); - CHIP_ERROR GetSetupPasscode(uint32_t & value); - CHIP_ERROR GetSpake2pSalt(MutableByteSpan & value); - CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & value, size_t & size); - - // - // DeviceAttestationCredentialsProvider - // - - CHIP_ERROR GetFirmwareInformation(MutableByteSpan & value); - CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & value); - CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & value); - CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & value); - CHIP_ERROR GetDeviceAttestationCSR(uint16_t vid, uint16_t pid, const CharSpan & cn, MutableCharSpan & csr); - CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & message, MutableByteSpan & signature); - - CHIP_ERROR SetCertificationDeclaration(const ByteSpan & value); - CHIP_ERROR SetProductAttestationIntermediateCert(const ByteSpan & value); - CHIP_ERROR SetDeviceAttestationCert(const ByteSpan & value); - CHIP_ERROR SetDeviceAttestationKey(const ByteSpan & value); - // - // Other - // - - CHIP_ERROR SetCredentialsBaseAddress(uint32_t addr); - CHIP_ERROR GetCredentialsBaseAddress(uint32_t & addr); - CHIP_ERROR GetSetupPayload(chip::MutableCharSpan & value); - CHIP_ERROR SetProvisionRequest(bool value); - CHIP_ERROR GetProvisionRequest(bool & value); - -#ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED - /** - * @brief Reads the test event trigger key from NVM. If the key isn't present, returns default value if defined. - * - * @param[out] keySpan output buffer. Must be at least large enough for 16 bytes (key length) - * @return CHIP_ERROR - */ - CHIP_ERROR GetTestEventTriggerKey(MutableByteSpan & keySpan); -#endif // SL_MATTER_TEST_EVENT_TRIGGER_ENABLED - - void SetBufferSize(size_t size) { mBufferSize = size > 0 ? size : kArgumentSizeMax; } - size_t GetBufferSize() { return mBufferSize > 0 ? mBufferSize : kArgumentSizeMax; } - -private: - // Generic Interface - CHIP_ERROR Set(uint16_t id, const uint8_t * value) override; - CHIP_ERROR Set(uint16_t id, const uint16_t * value) override; - CHIP_ERROR Set(uint16_t id, const uint32_t * value) override; - CHIP_ERROR Set(uint16_t id, const uint64_t * value) override; - CHIP_ERROR Set(uint16_t id, const uint8_t * value, size_t size) override; - // DeviceInstanceInfoProvider - CHIP_ERROR SetSerialNumber(const char * value, size_t len); - CHIP_ERROR SetVendorId(uint16_t value); - CHIP_ERROR SetVendorName(const char * value, size_t len); - CHIP_ERROR SetProductId(uint16_t productId); - CHIP_ERROR SetProductName(const char * value, size_t len); - CHIP_ERROR SetProductLabel(const char * value, size_t len); - CHIP_ERROR SetProductURL(const char * value, size_t len); - CHIP_ERROR SetPartNumber(const char * value, size_t len); - CHIP_ERROR SetHardwareVersion(uint16_t value); - CHIP_ERROR SetHardwareVersionString(const char * value, size_t len); - CHIP_ERROR SetManufacturingDate(const char * value, size_t len); - CHIP_ERROR GetManufacturingDate(uint8_t * value, size_t max, size_t & size); - // PersistentUniqueId is used to generate the RotatingUniqueId - // This PersistentUniqueId SHALL NOT be the same as the UniqueID attribute exposed in the Basic Information cluster. - CHIP_ERROR SetPersistentUniqueId(const uint8_t * value, size_t size); - CHIP_ERROR GetPersistentUniqueId(uint8_t * value, size_t max, size_t & size); - // CommissionableDataProvider - CHIP_ERROR SetSetupDiscriminator(uint16_t value); - CHIP_ERROR SetSpake2pIterationCount(uint32_t value); - CHIP_ERROR SetSetupPasscode(uint32_t value); - CHIP_ERROR SetSpake2pSalt(const char * value, size_t size); - CHIP_ERROR GetSpake2pSalt(char * value, size_t max, size_t & size); - CHIP_ERROR SetSpake2pVerifier(const char * value, size_t size); - CHIP_ERROR GetSpake2pVerifier(char * value, size_t max, size_t & size); - // DeviceAttestationCredentialsProvider - CHIP_ERROR SetFirmwareInformation(const ByteSpan & value); - - // Other - CHIP_ERROR SetProvisionVersion(const char * value, size_t len); - CHIP_ERROR GetProvisionVersion(char * value, size_t max, size_t & size); - CHIP_ERROR SetSetupPayload(const uint8_t * value, size_t size); - CHIP_ERROR GetSetupPayload(uint8_t * value, size_t max, size_t & size); -#if OTA_ENCRYPTION_ENABLE - CHIP_ERROR SetOtaTlvEncryptionKey(const ByteSpan & value); -#endif - - uint16_t mVendorId = 0; - uint16_t mProductId = 0; - uint16_t mHwVersion = 0; - uint16_t mDiscriminator = 0; // 12-bit - uint32_t mCommissioningFlow = 0; - uint32_t mRendezvousFlags = 0; - uint32_t mPasscode = 0; - uint32_t mKeyId = 0; - uint32_t mBufferSize = kArgumentSizeMax; - char mCommonName[kCommonNameMax] = { 0 }; - CustomStorage mCustom; -}; - -} // namespace Provision -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/provision/ProvisionStorageGeneric.h b/src/platform/silabs/provision/ProvisionStorageGeneric.h deleted file mode 100644 index 6c3cdc2c42..0000000000 --- a/src/platform/silabs/provision/ProvisionStorageGeneric.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - */ -#pragma once - -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { -namespace Provision { - -struct GenericStorage -{ - virtual ~GenericStorage() = default; - - virtual CHIP_ERROR Set(uint16_t id, const uint8_t * value) = 0; - virtual CHIP_ERROR Get(uint16_t id, uint8_t & value) = 0; - virtual CHIP_ERROR Set(uint16_t id, const uint16_t * value) = 0; - virtual CHIP_ERROR Get(uint16_t id, uint16_t & value) = 0; - virtual CHIP_ERROR Set(uint16_t id, const uint32_t * value) = 0; - virtual CHIP_ERROR Get(uint16_t id, uint32_t & value) = 0; - virtual CHIP_ERROR Set(uint16_t id, const uint64_t * value) = 0; - virtual CHIP_ERROR Get(uint16_t id, uint64_t & value) = 0; - virtual CHIP_ERROR Get(uint16_t id, uint8_t * value, size_t max_size, size_t & size) = 0; - virtual CHIP_ERROR Set(uint16_t id, const uint8_t * value, size_t size) = 0; -}; - -} // namespace Provision -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/provision/args.gni b/src/platform/silabs/provision/args.gni deleted file mode 100644 index a92793192b..0000000000 --- a/src/platform/silabs/provision/args.gni +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2020 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. - -import("//build_overrides/chip.gni") - -declare_args() { - sl_provision_root = "${chip_root}/src/platform/silabs/provision" -} diff --git a/src/platform/silabs/wifi/BUILD.gn b/src/platform/silabs/wifi/BUILD.gn index b7b652037b..d4877fcfd1 100644 --- a/src/platform/silabs/wifi/BUILD.gn +++ b/src/platform/silabs/wifi/BUILD.gn @@ -141,7 +141,7 @@ source_set("wifi-platform") { "${silabs_platform_dir}/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h", # Wi-Fi Config - Using the file sdk support until the wiseconnect file is fixed - "${sdk_support_root}/components/service/network_manager/src/sl_net_for_lwip.c", + "${matter_support_root}/sdk-copies/components/service/network_manager/src/sl_net_for_lwip.c", ] public_deps += [ "${lwip_root}:lwip" ] diff --git a/src/platform/silabs/wifi/rs911x/rs9117.gni b/src/platform/silabs/wifi/rs911x/rs9117.gni index 555ba88df9..7516584739 100644 --- a/src/platform/silabs/wifi/rs911x/rs9117.gni +++ b/src/platform/silabs/wifi/rs911x/rs9117.gni @@ -45,7 +45,7 @@ rs9117_src_sapi = [ "${wifi_sdk_root}/components/device/silabs/si91x/wireless/ncp_interface/sl_si91x_ncp_driver.c", # Wi-Fi Config - Using the file sdk support until the wiseconnect file is fixed - "${sdk_support_root}/components/service/network_manager/src/sl_net_for_lwip.c", + "${matter_support_root}/sdk-copies/components/service/network_manager/src/sl_net_for_lwip.c", # wifi component "${wifi_sdk_root}/components/protocol/wifi/src/sl_wifi_basic_credentials.c", diff --git a/src/test_driver/efr32/BUILD.gn b/src/test_driver/efr32/BUILD.gn index 1ff7a3a505..736e990ac9 100644 --- a/src/test_driver/efr32/BUILD.gn +++ b/src/test_driver/efr32/BUILD.gn @@ -18,9 +18,10 @@ import("//build_overrides/efr32_sdk.gni") import("//build_overrides/pigweed.gni") import("${build_root}/config/defaults.gni") -import("${chip_root}/src/platform/silabs/provision/args.gni") import("${silabs_sdk_build_root}/efr32_sdk.gni") +import("${matter_support_root}/provision/args.gni") + import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") import("${chip_root}/src/platform/device.gni") @@ -96,7 +97,7 @@ source_set("efr32_test_main") { "${chip_root}/src/lib", "${chip_root}/src/lib/support:pw_tests_wrapper", "${examples_common_plat_dir}/pw_sys_io:pw_sys_io_silabs", - "${sl_provision_root}:provision-headers", + "${sl_provision_root}:headers", ] # OpenThread Settings @@ -111,7 +112,7 @@ source_set("efr32_test_main") { deps += pw_build_LINK_DEPS libs = [ - "${sdk_support_root}/matter/provision/lib/libProvision_${silabs_family}.a", + "${matter_support_root}/provision/libs/libProvision_${silabs_family}.a", ] include_dirs = [ "${chip_root}/examples/common/pigweed/efr32" ] diff --git a/src/test_driver/efr32/src/main.cpp b/src/test_driver/efr32/src/main.cpp index 088dc4e870..3558f8e701 100644 --- a/src/test_driver/efr32/src/main.cpp +++ b/src/test_driver/efr32/src/main.cpp @@ -22,9 +22,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include diff --git a/third_party/openthread/platforms/efr32/BUILD.gn b/third_party/openthread/platforms/efr32/BUILD.gn index 88f8f44c10..9ef8422cbc 100644 --- a/third_party/openthread/platforms/efr32/BUILD.gn +++ b/third_party/openthread/platforms/efr32/BUILD.gn @@ -31,8 +31,8 @@ config("openthread_efr32_config") { include_dirs = [ "${sl_ot_efr32_root}", "${chip_root}/examples/platform/efr32", - "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}", - "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/config", + "${matter_support_root}/board-support/efr32/${silabs_family}/${silabs_board}", + "${matter_support_root}/board-support/efr32/${silabs_family}/${silabs_board}/config", "${sl_ot_platform_abstraction}/include", "${sl_ot_platform_abstraction}/rtos", ] @@ -74,7 +74,7 @@ source_set("libopenthread-efr32") { "${sl_ot_efr32_root}/system.c", # Temporary file until the files in the SI SDK is fixed - "${sdk_support_root}/protocol/openthread/platform-abstraction/efr32/radio.c", + "${matter_support_root}/sdk-copies/protocol/openthread/platform-abstraction/efr32/radio.c", ] include_dirs = [ "${openthread_root}/examples/platforms/utils" ] diff --git a/third_party/silabs/BUILD.gn b/third_party/silabs/BUILD.gn index b1f7b6bd5e..45f81cf18c 100644 --- a/third_party/silabs/BUILD.gn +++ b/third_party/silabs/BUILD.gn @@ -103,7 +103,7 @@ if (wifi_soc != true) { # CCP board include_dirs = [ "${chip_root}/examples/platform/silabs/efr32", "${chip_root}/examples/platform/silabs", - "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}", + "${matter_support_root}/board-support/efr32/${silabs_family}/${silabs_board}", "${sl_ot_efr32_root}", "${openthread_root}/src/", "${openthread_root}/third_party/tcplp", @@ -149,7 +149,7 @@ if (wifi_soc != true) { # CCP board "${sl_ot_libs_path}/src/stubs/tcp/tcp_stubs.c", # Temporary file until the files in the SI SDK is fixed - "${sdk_support_root}/protocol/openthread/platform-abstraction/efr32/radio.c", + "${matter_support_root}/sdk-copies/protocol/openthread/platform-abstraction/efr32/radio.c", ] include_dirs = [ diff --git a/third_party/silabs/SiWx917_sdk.gni b/third_party/silabs/SiWx917_sdk.gni index de6d6689c0..9c1a1a2d58 100644 --- a/third_party/silabs/SiWx917_sdk.gni +++ b/third_party/silabs/SiWx917_sdk.gni @@ -60,8 +60,8 @@ template("siwx917_sdk") { "${efr32_sdk_root}/platform/emdrv/nvm3/inc", "${efr32_sdk_root}/platform/emdrv/common/inc", "${efr32_sdk_root}/platform/service/device_init/inc", - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen", - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/config", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/config", "${chip_root}/src/platform/silabs/rs911x", "${chip_root}/src/platform/silabs/wifi", @@ -132,7 +132,7 @@ template("siwx917_sdk") { "${efr32_sdk_root}/platform/service/sleeptimer/inc", "${efr32_sdk_root}/platform/service/sleeptimer/config", "${efr32_sdk_root}/platform/service/sleeptimer/src", - "${sdk_support_root}/matter/si91x/support/inc", + "${matter_support_root}/board-support/si91x/support/inc", "${efr32_sdk_root}/platform/service/iostream/inc", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/hardware_drivers/button/inc", @@ -561,7 +561,7 @@ template("siwx917_sdk") { "${efr32_sdk_root}/platform/security/sl_component/sli_psec_osal/inc", # tinycrypt specific headers - "${sdk_support_root}/matter/mbedtls/tinycrypt/inc", + "${matter_support_root}/tinycrypt/inc", ] } @@ -614,10 +614,10 @@ template("siwx917_sdk") { "${_mbedtls_root}/library/x509write_csr.c", # tinycrypt - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc_dh.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc_dsa.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/tinycrypt_util.c", + "${matter_support_root}/tinycrypt/src/ecc.c", + "${matter_support_root}/tinycrypt/src/ecc_dh.c", + "${matter_support_root}/tinycrypt/src/ecc_dsa.c", + "${matter_support_root}/tinycrypt/src/tinycrypt_util.c", # Sisdk platform/security "${efr32_sdk_root}/platform/security/sl_component/sli_psec_osal/src/sli_psec_osal_cmsis_rtos2.c", @@ -741,11 +741,11 @@ template("siwx917_sdk") { "${efr32_sdk_root}/util/third_party/freertos/kernel/stream_buffer.c", "${efr32_sdk_root}/util/third_party/freertos/kernel/tasks.c", "${efr32_sdk_root}/util/third_party/freertos/kernel/timers.c", - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_event_handler.c", - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_iostream_handles.c", - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_si91x_button_instances.c", - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_ulp_timer_init.c", - "${sdk_support_root}/matter/si91x/support/hal/rsi_hal_mcu_m4.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_event_handler.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_iostream_handles.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_si91x_button_instances.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_ulp_timer_init.c", + "${matter_support_root}/board-support/si91x/support/hal/rsi_hal_mcu_m4.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/hardware_drivers/button/src/sl_si91x_button.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/service/clock_manager/src/sl_si91x_clock_manager.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/service/clock_manager/src/sli_si91x_clock_manager.c", @@ -764,7 +764,7 @@ template("siwx917_sdk") { # STARTUP FILES "${efr32_sdk_root}/platform/service/iostream/src/sl_iostream.c", "${efr32_sdk_root}/platform/service/iostream/src/sl_iostream_rtt.c", - "${sdk_support_root}/matter/si91x/support/src/startup_common_RS1xxxx.c", + "${matter_support_root}/board-support/si91x/support/src/startup_common_RS1xxxx.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/service/nvm3/src/sl_si91x_common_flash_intf.c", # OTA @@ -775,12 +775,12 @@ template("siwx917_sdk") { if (sl_enable_rgb_led) { sources += [ - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_si91x_rgb_led_instances.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_si91x_rgb_led_instances.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/hardware_drivers/rgb_led/src/sl_si91x_rgb_led.c", ] } else { sources += [ - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_si91x_led_instances.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_si91x_led_instances.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/hardware_drivers/led/src/sl_si91x_led.c", ] } @@ -828,8 +828,8 @@ template("siwx917_sdk") { if (chip_enable_icd_server) { sources += [ - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_si91x_power_manager_handler.c", - "${sdk_support_root}/matter/si91x/siwx917/${silabs_board}/autogen/sl_si91x_power_manager_wakeup_handler.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_si91x_power_manager_handler.c", + "${matter_support_root}/board-support/si91x/siwx917/${silabs_board}/autogen/sl_si91x_power_manager_wakeup_handler.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/sl_si91x_m4_ps.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sl_si91x_power_manager.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sli_si91x_power_manager.c", diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index f410f05149..c7793b8e5a 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -24,7 +24,7 @@ import("silabs_board.gni") declare_args() { # Location of the efr32 SDK. efr32_sdk_root = "${chip_root}/third_party/silabs/simplicity_sdk" - sdk_support_root = "${chip_root}/third_party/silabs/matter_support" + matter_support_root = "${chip_root}/third_party/silabs/matter_support" wiseconnect_sdk_root = "${chip_root}/third_party/silabs/wiseconnect-wifi-bt-sdk" wifi_sdk_root = "${chip_root}/third_party/silabs/wifi_sdk" @@ -117,8 +117,7 @@ declare_args() { "${efr32_sdk_root}/protocol/openthread/platform-abstraction" # board related pre-generated files path (default) - sl_pre_gen_path = - "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/" + sl_pre_gen_path = "${matter_support_root}/board-support/efr32/${silabs_family}/${silabs_board}/" # board related generated files path (used if slc_generate or slc_reuse_files is set) slc_gen_path = "${chip_root}/third_party/silabs/slc_gen/${silabs_board}/" @@ -246,7 +245,7 @@ template("efr32_sdk") { "${efr32_sdk_root}/util/third_party/openthread/include", "${efr32_sdk_root}/util/third_party/openthread/src/core", "${efr32_sdk_root}/util/third_party/openthread/examples/platforms/", - "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/config", + "${matter_support_root}/board-support/efr32/${silabs_family}/${silabs_board}/config", # Headers needed for Init no function will be called if OT is not used "${sl_ot_efr32_root}", @@ -263,22 +262,22 @@ template("efr32_sdk") { "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure", ] - libs += [ "${sdk_support_root}/protocol/openthread/libs/libsl_openthread_cm33_gcc.a" ] + libs += [ "${matter_support_root}/sdk-copies/protocol/openthread/libs/libsl_openthread_cm33_gcc.a" ] if (!chip_enable_ble_rs911x) { libs += [ - "${sdk_support_root}/protocol/bluetooth/bgcommon/lib/build/gcc/cortex-m33/bgcommon/release/libbgcommon.a", - "${sdk_support_root}/protocol/bluetooth/bgstack/ll/build/gcc/xg24/release/liblinklayer.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/ble_bgapi/release/libble_bgapi_gatt_server.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/bgapi_protocol/api3/release/libbgapi_core.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/accept_list/release/libble_host_accept_list_stub.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/bgstack/release/libble_host.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/bgstack/release/libbondingdb_stub.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/ble_bgapi/release/libble_bgapi.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/ble_bgapi/release/libble_bgapi_stub_gatt_client.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/hal/release/libble_host_hal_series2.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/hci/release/libble_host_hci.a", - "${sdk_support_root}/protocol/bluetooth/build/gcc/cortex-m33/ble_host/system/release/libble_system.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/bgcommon/lib/build/gcc/cortex-m33/bgcommon/release/libbgcommon.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/bgstack/ll/build/gcc/xg24/release/liblinklayer.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/ble_bgapi/release/libble_bgapi_gatt_server.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/bgapi_protocol/api3/release/libbgapi_core.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/accept_list/release/libble_host_accept_list_stub.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/bgstack/release/libble_host.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/bgstack/release/libbondingdb_stub.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/ble_bgapi/release/libble_bgapi.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/ble_bgapi/release/libble_bgapi_stub_gatt_client.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/hal/release/libble_host_hal_series2.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/hci/release/libble_host_hci.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/build/gcc/cortex-m33/ble_host/system/release/libble_system.a", ] } } @@ -292,10 +291,10 @@ template("efr32_sdk") { "${efr32_sdk_root}/platform/emdrv/spidrv/config", ] - libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg24_gcc_release.a" ] + libs += [ "${matter_support_root}/sdk-copies/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg24_gcc_release.a" ] if (!chip_enable_ble_rs911x) { - libs += [ "${sdk_support_root}/protocol/bluetooth/bgstack/ll/build/gcc/xg24/release/liblinklayer.a" ] + libs += [ "${matter_support_root}/sdk-copies/protocol/bluetooth/bgstack/ll/build/gcc/xg24/release/liblinklayer.a" ] } defines += [ "EFR32MG24" ] @@ -307,18 +306,18 @@ template("efr32_sdk") { ] libs += [ - "${sdk_support_root}/protocol/bluetooth/bgstack/ll/build/gcc/xg24/release/liblinklayer.a", - "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_module_efr32xg24_gcc_release.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/bgstack/ll/build/gcc/xg24/release/liblinklayer.a", + "${matter_support_root}/sdk-copies/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_module_efr32xg24_gcc_release.a", ] if (silabs_mcu == "MGM240PB32VNA") { - libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb32vna_gcc.a" ] + libs += [ "${matter_support_root}/sdk-copies/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb32vna_gcc.a" ] } else if (silabs_mcu == "MGM240PB22VNA") { - libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb22vna_gcc.a" ] + libs += [ "${matter_support_root}/sdk-copies/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb22vna_gcc.a" ] } else if (silabs_mcu == "MGM240L022RNF") { - libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240l022rnf_gcc.a" ] + libs += [ "${matter_support_root}/sdk-copies/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240l022rnf_gcc.a" ] } else if (silabs_mcu == "MGM240SD22VNA") { - libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240sd22vna_gcc.a" ] + libs += [ "${matter_support_root}/sdk-copies/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240sd22vna_gcc.a" ] defines += [ "SLI_RADIOAES_REQUIRES_MASKING=1" ] } @@ -331,8 +330,8 @@ template("efr32_sdk") { ] libs += [ - "${sdk_support_root}/protocol/bluetooth/bgstack/ll/build/gcc/xg26/release/liblinklayer.a", - "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg26_gcc_release.a", + "${matter_support_root}/sdk-copies/protocol/bluetooth/bgstack/ll/build/gcc/xg26/release/liblinklayer.a", + "${matter_support_root}/sdk-copies/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg26_gcc_release.a", ] defines += [ "EFR32MG26" ] @@ -1119,7 +1118,7 @@ template("efr32_sdk") { "${efr32_sdk_root}/platform/common/src/sl_status.c", "${efr32_sdk_root}/platform/driver/i2cspm/src/sl_i2cspm.c", "${efr32_sdk_root}/platform/emlib/src/em_i2c.c", - "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_i2cspm_init.c", + "${matter_support_root}/board-support/efr32/${silabs_family}/${silabs_board}/autogen/sl_i2cspm_init.c", ] } diff --git a/third_party/silabs/matter_support b/third_party/silabs/matter_support index 7ad2bdc6c2..3a9a442a0a 160000 --- a/third_party/silabs/matter_support +++ b/third_party/silabs/matter_support @@ -1 +1 @@ -Subproject commit 7ad2bdc6c2c100ee6775b76b6cd055c40d29e117 +Subproject commit 3a9a442a0abbe4077309ee2b853a0dd442aadd01 From 80121987e21275c7a05a7c915031cb0e73a846e7 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Tue, 11 Mar 2025 07:51:22 -0400 Subject: [PATCH 3/9] [SL-TEMP] Update CODEOWNERS (#330) --- .github/CODEOWNERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6f9c886ea9..50fbcaf004 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,5 +1,4 @@ # Default codeowners for the repository -* @SiliconLabsSoftware/matter-watt-reviewers - +* @SiliconLabsSoftware/matter-codeowners #codeowners for the CODEOWNERS file /.github/CODEOWNERS @SiliconLabsSoftware/matter-admin From 6543569fe22d949f24cb15808c8b9c12d8b6651c Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Tue, 11 Mar 2025 11:33:24 -0400 Subject: [PATCH 4/9] =?UTF-8?q?[CSA-CP]=20temporary=20workaround:=20keepin?= =?UTF-8?q?g=20pygobject=3D=3D3.50.0=20to=20avoid=20dependency=20i?= =?UTF-8?q?=E2=80=A6=20(#334)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Amine Alami <43780877+Alami-Amine@users.noreply.github.com> --- src/controller/python/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/python/BUILD.gn b/src/controller/python/BUILD.gn index 58d9cb1f7c..e8573af616 100644 --- a/src/controller/python/BUILD.gn +++ b/src/controller/python/BUILD.gn @@ -394,7 +394,7 @@ chip_python_wheel_action("chip-repl") { } else if (current_os == "linux") { py_package_reqs += [ "dbus-python==1.2.18", - "pygobject", + "pygobject==3.50.0", ] } From c26cd9197b31f504970c30dc804caa233a20abde Mon Sep 17 00:00:00 2001 From: sarthak shaha Date: Tue, 11 Mar 2025 14:00:16 -0400 Subject: [PATCH 5/9] [CSA-CP] remove extern air quality (#335) Co-authored-by: Restyled.io --- .../platform/silabs/sensors/AirQuality/AirQualitySensor.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp index e693a26021..c00d4e4a48 100644 --- a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp +++ b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp @@ -22,12 +22,8 @@ #include #ifdef USE_SPARKFUN_AIR_QUALITY_SENSOR -#ifdef __cplusplus -extern "C" { -#endif -#include -} #include "sl_i2cspm_instances.h" +#include #endif // USE_SPARKFUN_AIR_QUALITY_SENSOR namespace { From 621f8ddec9d44675a369141bf603cff2b617508c Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Tue, 11 Mar 2025 19:43:45 -0400 Subject: [PATCH 6/9] [CSA-CP] User label max entry limit (#336) Co-authored-by: Yufeng Wang --- .../user-label-server/user-label-server.cpp | 1 + .../TestUserLabelClusterConstraints.yaml | 32 +++++++++++++++++++ src/platform/DeviceInfoProvider.cpp | 11 +++++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/app/clusters/user-label-server/user-label-server.cpp b/src/app/clusters/user-label-server/user-label-server.cpp index 5daae5ab17..7b9beae71d 100644 --- a/src/app/clusters/user-label-server/user-label-server.cpp +++ b/src/app/clusters/user-label-server/user-label-server.cpp @@ -143,6 +143,7 @@ CHIP_ERROR UserLabelAttrAccess::WriteLabelList(const ConcreteDataAttributePath & return provider->SetUserLabelList(endpoint, labelList); } + if (aPath.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem) { Structs::LabelStruct::DecodableType entry; diff --git a/src/app/tests/suites/TestUserLabelClusterConstraints.yaml b/src/app/tests/suites/TestUserLabelClusterConstraints.yaml index 4074def78d..935fe88c2b 100644 --- a/src/app/tests/suites/TestUserLabelClusterConstraints.yaml +++ b/src/app/tests/suites/TestUserLabelClusterConstraints.yaml @@ -55,3 +55,35 @@ tests: ] response: error: CONSTRAINT_ERROR + + - label: "Attempt to write a large label list" + command: "writeAttribute" + attribute: "LabelList" + arguments: + value: [ + # Example repeated user labels to blow up the maximum allowed + { Label: "roomName", Value: "master bedroom 1" }, + { Label: "orientation", Value: "east" }, + { Label: "floor", Value: "2" }, + { Label: "roomType", Value: "bedroom" }, + { Label: "someKey5", Value: "someVal5" }, + { Label: "someKey6", Value: "someVal6" }, + { Label: "someKey7", Value: "someVal7" }, + { Label: "someKey8", Value: "someVal8" }, + { Label: "someKey9", Value: "someVal9" }, + { Label: "someKey10", Value: "someVal10" }, + { Label: "someKey11", Value: "someVal11" }, + { Label: "someKey12", Value: "someVal12" }, + { Label: "someKey13", Value: "someVal13" }, + { Label: "someKey14", Value: "someVal14" }, + { Label: "someKey15", Value: "someVal15" }, + { Label: "someKey16", Value: "someVal16" }, + { Label: "someKey17", Value: "someVal17" }, + { Label: "someKey18", Value: "someVal18" }, + { Label: "someKey19", Value: "someVal19" }, + { Label: "someKey20", Value: "someVal20" }, + ] + response: + # When the cluster runs out of capacity to store these entries, + # we expect a FAILURE get returned. + error: FAILURE diff --git a/src/platform/DeviceInfoProvider.cpp b/src/platform/DeviceInfoProvider.cpp index 92ad84d86d..28191cd4f8 100644 --- a/src/platform/DeviceInfoProvider.cpp +++ b/src/platform/DeviceInfoProvider.cpp @@ -82,11 +82,16 @@ CHIP_ERROR DeviceInfoProvider::AppendUserLabel(EndpointId endpoint, const UserLa { size_t length; - // Increase the size of UserLabelList by 1 + // Fetch current list length ReturnErrorOnFailure(GetUserLabelLength(endpoint, length)); - ReturnErrorOnFailure(SetUserLabelLength(endpoint, length + 1)); - // Append the user label at the end of UserLabelList + if (length >= kMaxUserLabelListLength) + { + return CHIP_ERROR_NO_MEMORY; + } + + // Add the new entry to the list + ReturnErrorOnFailure(SetUserLabelLength(endpoint, length + 1)); ReturnErrorOnFailure(SetUserLabelAt(endpoint, length, label)); return CHIP_NO_ERROR; From ce89c61943af4971b45c895ff08cd1e5aa8faf4e Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Tue, 11 Mar 2025 19:43:55 -0400 Subject: [PATCH 7/9] [CSA-CP] Fix Null Pointer Dereference in TCP Packet Handling (#337) Co-authored-by: BoB13-Matter Co-authored-by: Restyled.io --- src/transport/raw/TCP.cpp | 8 ++++++++ src/transport/raw/tests/TestTCP.cpp | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/transport/raw/TCP.cpp b/src/transport/raw/TCP.cpp index b73540d795..f12ee7892a 100644 --- a/src/transport/raw/TCP.cpp +++ b/src/transport/raw/TCP.cpp @@ -343,7 +343,15 @@ CHIP_ERROR TCPBase::ProcessReceivedBuffer(Inet::TCPEndPoint * endPoint, const Pe // We have not yet received the complete message. return CHIP_NO_ERROR; } + state->mReceived.Consume(kPacketSizeBytes); + + if (messageSize == 0) + { + // No payload but considered a valid message. Return success to keep the connection alive. + return CHIP_NO_ERROR; + } + ReturnErrorOnFailure(ProcessSingleMessage(peerAddress, state, messageSize)); } diff --git a/src/transport/raw/tests/TestTCP.cpp b/src/transport/raw/tests/TestTCP.cpp index 80531491f2..80d5670748 100644 --- a/src/transport/raw/tests/TestTCP.cpp +++ b/src/transport/raw/tests/TestTCP.cpp @@ -64,7 +64,8 @@ constexpr NodeId kSourceNodeId = 123654; constexpr NodeId kDestinationNodeId = 111222333; constexpr uint32_t kMessageCounter = 18; -const char PAYLOAD[] = "Hello!"; +const char PAYLOAD[] = "Hello!"; +const char messageSize_TEST[] = "\x00\x00\x00\x00"; class MockTransportMgrDelegate : public chip::TransportMgrDelegate { @@ -633,6 +634,12 @@ TEST_F(TestTCP, CheckProcessReceivedBuffer) TestData testData[2]; gMockTransportMgrDelegate.SetCallback(TestDataCallbackCheck, testData); + // Test a single packet buffer with zero message size. + System::PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(messageSize_TEST, 4); + ASSERT_NE(&buf, nullptr); + err = TestAccess::ProcessReceivedBuffer(tcp, lEndPoint, lPeerAddress, std::move(buf)); + EXPECT_EQ(err, CHIP_NO_ERROR); + // Test a single packet buffer. gMockTransportMgrDelegate.mReceiveHandlerCallCount = 0; EXPECT_TRUE(testData[0].Init((const uint32_t[]){ 111, 0 })); From 1f1eb53b6705286c3302c80360370985db736f5c Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Fri, 14 Mar 2025 11:50:12 -0400 Subject: [PATCH 8/9] =?UTF-8?q?[CSA-CP]=20Rename=20CLUSTER=5FMASK=5F=20and?= =?UTF-8?q?=20ATTIBUTE=5FMASK=20defines=20to=20differentiate=20with=20?= =?UTF-8?q?=E2=80=A6=20(#342)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AirQualitySensorAppAttrUpdateDelegate.cpp | 1 - .../linux/AllClustersCommandDelegate.cpp | 1 - .../all-clusters-app/linux/main-common.cpp | 1 - .../linux/main-common.cpp | 1 - examples/bridge-app/esp32/README.md | 8 +- examples/bridge-app/linux/README.md | 8 +- examples/bridge-app/telink/README.md | 8 +- .../clusters/switch/SwitchEventHandler.cpp | 1 - .../common/clusters/switch/SwitchManager.cpp | 1 - examples/chef/esp32/main/main.cpp | 1 - examples/fabric-bridge-app/linux/README.md | 8 +- examples/fabric-sync/README.md | 185 +++ .../linux/LightingAppCommandDelegate.cpp | 1 - .../infineon/cyw30739/src/LightingManager.cpp | 1 - .../linux/LightingAppCommandDelegate.cpp | 1 - src/app/AttributePathExpandIterator-Ember.cpp | 3 +- .../group-key-mgmt-server.cpp | 1 - .../clusters/groups-server/groups-server.cpp | 3 +- .../mode-select-server/mode-select-server.cpp | 1 - .../clusters/on-off-server/on-off-server.cpp | 9 +- .../clusters/scenes-server/scenes-server.h | 2 + .../EmberMetadata.cpp | 2 +- .../tests/TestCodegenModelViaMocks.cpp | 9 +- src/app/dynamic_server/DynamicDispatcher.cpp | 7 +- src/app/tests/TestSceneTable.cpp | 36 +- src/app/util/BUILD.gn | 1 - src/app/util/af-types.h | 49 +- src/app/util/att-storage.h | 33 - src/app/util/attribute-metadata.h | 34 +- src/app/util/attribute-storage-detail.h | 1 - src/app/util/attribute-storage.cpp | 38 +- src/app/util/attribute-storage.h | 13 +- src/app/util/attribute-table.cpp | 2 +- .../util/ember-compatibility-functions.cpp | 7 +- src/app/util/endpoint-config-defines.h | 4 +- src/app/util/mock/MockNodeConfig.cpp | 4 +- src/app/util/mock/MockNodeConfig.h | 4 +- src/app/util/mock/attribute-storage.cpp | 3 +- src/controller/tests/TestWriteChunking.cpp | 4 +- .../CHIP/ServerEndpoint/MTRIMDispatch.mm | 1 - .../CHIP/ServerEndpoint/MTRServerCluster.mm | 2 +- .../CHIP/ServerEndpoint/MTRServerEndpoint.mm | 7 +- .../tests/TestEmberAttributeDataBuffer.cpp | 1179 +++++++++++++++++ 43 files changed, 1495 insertions(+), 191 deletions(-) create mode 100644 examples/fabric-sync/README.md delete mode 100644 src/app/util/att-storage.h create mode 100644 src/data-model-providers/codegen/tests/TestEmberAttributeDataBuffer.cpp diff --git a/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp b/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp index 7aaa873a90..b17db0107d 100644 --- a/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp +++ b/examples/air-quality-sensor-app/linux/AirQualitySensorAppAttrUpdateDelegate.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp index 0d66550940..e0278f30cc 100644 --- a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp +++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index b62d154f0d..6d8728da53 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include diff --git a/examples/all-clusters-minimal-app/linux/main-common.cpp b/examples/all-clusters-minimal-app/linux/main-common.cpp index d99927cea0..306a4b51a2 100644 --- a/examples/all-clusters-minimal-app/linux/main-common.cpp +++ b/examples/all-clusters-minimal-app/linux/main-common.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/examples/bridge-app/esp32/README.md b/examples/bridge-app/esp32/README.md index ac22c7f8b3..2a0bde25f5 100644 --- a/examples/bridge-app/esp32/README.md +++ b/examples/bridge-app/esp32/README.md @@ -54,10 +54,10 @@ defined: definition. - All attributes defined with these macros will be configured as - `ATTRIBUTE_MASK_EXTERNAL_STORAGE` in the ZCL database and therefore will - rely on the application to maintain storage for the attribute. Consequently, - reads or writes to these attributes must be handled within the application - by the `emberAfExternalAttributeWriteCallback` and + `MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE` in the ZCL database and therefore + will rely on the application to maintain storage for the attribute. + Consequently, reads or writes to these attributes must be handled within the + application by the `emberAfExternalAttributeWriteCallback` and `emberAfExternalAttributeReadCallback` functions. See the bridge application's `main.cpp` for an example of this implementation. diff --git a/examples/bridge-app/linux/README.md b/examples/bridge-app/linux/README.md index a416923669..6502655685 100644 --- a/examples/bridge-app/linux/README.md +++ b/examples/bridge-app/linux/README.md @@ -45,10 +45,10 @@ defined: definition. - All attributes defined with these macros will be configured as - `ATTRIBUTE_MASK_EXTERNAL_STORAGE` in the ZCL database and therefore will - rely on the application to maintain storage for the attribute. Consequently, - reads or writes to these attributes must be handled within the application - by the `emberAfExternalAttributeWriteCallback` and + `MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE` in the ZCL database and therefore + will rely on the application to maintain storage for the attribute. + Consequently, reads or writes to these attributes must be handled within the + application by the `emberAfExternalAttributeWriteCallback` and `emberAfExternalAttributeReadCallback` functions. See the bridge application's `main.cpp` for an example of this implementation. diff --git a/examples/bridge-app/telink/README.md b/examples/bridge-app/telink/README.md index 00b050e93c..2dccc834cb 100644 --- a/examples/bridge-app/telink/README.md +++ b/examples/bridge-app/telink/README.md @@ -56,10 +56,10 @@ defined: definition. - All attributes defined with these macros will be configured as - `ATTRIBUTE_MASK_EXTERNAL_STORAGE` in the ZCL database and therefore will - rely on the application to maintain storage for the attribute. Consequently, - reads or writes to these attributes must be handled within the application - by the `emberAfExternalAttributeWriteCallback` and + `MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE` in the ZCL database and therefore + will rely on the application to maintain storage for the attribute. + Consequently, reads or writes to these attributes must be handled within the + application by the `emberAfExternalAttributeWriteCallback` and `emberAfExternalAttributeReadCallback` functions. See the bridge application's `main.cpp` for an example of this implementation. diff --git a/examples/chef/common/clusters/switch/SwitchEventHandler.cpp b/examples/chef/common/clusters/switch/SwitchEventHandler.cpp index dd32e2b907..55fae2ae70 100644 --- a/examples/chef/common/clusters/switch/SwitchEventHandler.cpp +++ b/examples/chef/common/clusters/switch/SwitchEventHandler.cpp @@ -20,7 +20,6 @@ #ifdef MATTER_DM_PLUGIN_SWITCH_SERVER #include #include -#include #include #include "SwitchEventHandler.h" diff --git a/examples/chef/common/clusters/switch/SwitchManager.cpp b/examples/chef/common/clusters/switch/SwitchManager.cpp index 45d39dd4bc..c308cb1111 100644 --- a/examples/chef/common/clusters/switch/SwitchManager.cpp +++ b/examples/chef/common/clusters/switch/SwitchManager.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/examples/chef/esp32/main/main.cpp b/examples/chef/esp32/main/main.cpp index b61fcf22bc..460ac0c657 100644 --- a/examples/chef/esp32/main/main.cpp +++ b/examples/chef/esp32/main/main.cpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include "Display.h" diff --git a/examples/fabric-bridge-app/linux/README.md b/examples/fabric-bridge-app/linux/README.md index 27a01d9ffe..12a0ac2093 100644 --- a/examples/fabric-bridge-app/linux/README.md +++ b/examples/fabric-bridge-app/linux/README.md @@ -51,10 +51,10 @@ defined: definition. - All attributes defined with these macros will be configured as - `ATTRIBUTE_MASK_EXTERNAL_STORAGE` in the ZCL database and therefore will - rely on the application to maintain storage for the attribute. Consequently, - reads or writes to these attributes must be handled within the application - by the `emberAfExternalAttributeWriteCallback` and + `MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE` in the ZCL database and therefore + will rely on the application to maintain storage for the attribute. + Consequently, reads or writes to these attributes must be handled within the + application by the `emberAfExternalAttributeWriteCallback` and `emberAfExternalAttributeReadCallback` functions. See the bridge application's `main.cpp` for an example of this implementation. diff --git a/examples/fabric-sync/README.md b/examples/fabric-sync/README.md new file mode 100644 index 0000000000..ab08bd42af --- /dev/null +++ b/examples/fabric-sync/README.md @@ -0,0 +1,185 @@ +# Matter Linux Fabric Sync Example + +An example application to implement the Fabric Synchronization feature and +demonstrates the end-to-end Fabric Synchronization feature using dynamic +endpoints. + +Fabric Synchronization feature will facilitate the commissioning of end devices +from one fabric to another without requiring user intervention for every end +device. It defines mechanisms that can be used by multiple +ecosystems/controllers to communicate with one another to simplify the +experience for users. + +This doc is tested on **Ubuntu 22.04 LTS (aarch64)** + +
+ +- [Matter Linux Fabric Sync Example](#matter-linux-fabric-sync-example) + - [Theory of Operation](#theory-of-operation) + - [Building](#building) + - [Running the Complete Example on Ubuntu](#running-the-complete-example-on-ubuntu) + +
+ +## Theory of Operation + +### Dynamic Endpoints + +The Fabric-Sync Example makes use of Dynamic Endpoints. Current SDK support is +limited for dynamic endpoints, since endpoints are typically defined (along with +the clusters and attributes they contain) in a .zap file which then generates +code and static structures to define the endpoints. + +To support endpoints that are not statically defined, the ZCL attribute storage +mechanisms will hold additional endpoint information for `NUM_DYNAMIC_ENDPOINTS` +additional endpoints. These additional endpoint structures must be defined by +the application and can change at runtime. + +To facilitate the creation of these endpoint structures, several macros are +defined: + +`DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(attrListName)` +`DECLARE_DYNAMIC_ATTRIBUTE(attId, attType, attSizeBytes, attrMask)` +`DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(clusterRevision)` + +- These three macros are used to declare a list of attributes for use within a + cluster. The declaration must begin with the + `DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN` macro which will define the name of + the allocated attribute structure. Each attribute is then added by the + `DECLARE_DYNAMIC_ATTRIBUTE` macro. Finally, + `DECLARE_DYNAMIC_ATTRIBUTE_LIST_END` macro should be used to close the + definition. + +- All attributes defined with these macros will be configured as + `MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE` in the ZCL database and therefore + will rely on the application to maintain storage for the attribute. + Consequently, reads or writes to these attributes must be handled within the + application by the `emberAfExternalAttributeWriteCallback` and + `emberAfExternalAttributeReadCallback` functions. See the bridge + application's `main.cpp` for an example of this implementation. + +`DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(clusterListName)` +`DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs, role, incomingCommands, outgoingCommands)` +`DECLARE_DYNAMIC_CLUSTER_LIST_END` + +- These three macros are used to declare a list of clusters for use within a + endpoint. The declaration must begin with the + `DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN` macro which will define the name of the + allocated cluster structure. Each cluster is then added by the + `DECLARE_DYNAMIC_CLUSTER` macro referencing attribute list previously + defined by the `DECLARE_DYNAMIC_ATTRIBUTE...` macros and the lists of + incoming/outgoing commands terminated by kInvalidCommandId (or nullptr if + there aren't any commands in the list). Finally, + `DECLARE_DYNAMIC_CLUSTER_LIST_END` macro should be used to close the + definition. + +`DECLARE_DYNAMIC_ENDPOINT(endpointName, clusterList)` + +- This macro is used to declare an endpoint and its associated cluster list, + which must be previously defined by the `DECLARE_DYNAMIC_CLUSTER...` macros. + +## Building + +- For Linux host example: + + ```sh + source scripts/activate.sh + ./scripts/build/build_examples.py --target linux-x64-fabric-sync-no-ble build + ``` + +- For Raspberry Pi 4 example: + + Pull Docker Images + + ```sh + docker pull ghcr.io/project-chip/chip-build-crosscompile:112 + ``` + + Run docker + + ```sh + docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:112 /bin/bash + ``` + + Build + + ```sh + cd /var/connectedhomeip + + git config --global --add safe.directory /var/connectedhomeip + + ./scripts/run_in_build_env.sh \ + "./scripts/build/build_examples.py \ + --target linux-arm64-fabric-sync-no-ble-clang \ + build" + ``` + + Transfer the fabric-bridge-app binary to a Raspberry Pi + + ```sh + scp ./fabric-sync ubuntu@xxx.xxx.xxx.xxx:/home/ubuntu + ``` + +## Running the Complete Example on Ubuntu + +- Building + + Follow [Building](#building) section of this document. + +- Run Linux Fabric Sync Example App on two Linux machine E1 and E2 + + ```sh + sudo rm -rf /tmp/chip_* + cd ~/connectedhomeip/ + out/debug/fabric-sync + ``` + +- Initiate the FS Setup Process from E1 to E2 + + ```sh + > app add-bridge 1 20202021 192.168.86.246 5540 + Done + > New device with Node ID: 0000000000000001 has been successfully added. + A new device has been added on Endpoint: 2. + ``` + +- Verify Reverse Commissioning of the Fabric-Bridge from E1 on E2 + + ```sh + > New device with Node ID: 0000000000000002 has been successfully added. + ``` + +- Pair Light Example to E2 + + Since Fabric-Bridge also functions as a Matter server, running it alongside + the Light Example app on the same machine would cause conflicts. Therefore, + you need to run the Matter Light Example app on a separate physical machine + from the one hosting Fabric-Sync. + + ```sh + > app add-device 3 + ``` + + After the device is successfully added, you will observe the following + message on E2 with the newly assigned Node ID: + + ```sh + > New device with Node ID: 0x3 has been successfully added. + ``` + + Additionally, you should also get notified when a new device is added to E2 + from the E1: + + ```sh + > A new device is added on Endpoint 3. + ``` + +- Synchronize Light Example to E1 + + After the Light Example is successfully paired in E2, we can start to + synchronize the light device to E1 using the new assigned dynamic endpointid + on Ecosystem 2. + + ```sh + > app sync-device + ``` diff --git a/examples/lighting-app-data-mode-no-unique-id/linux/LightingAppCommandDelegate.cpp b/examples/lighting-app-data-mode-no-unique-id/linux/LightingAppCommandDelegate.cpp index cc5af976eb..c6d1cdead6 100644 --- a/examples/lighting-app-data-mode-no-unique-id/linux/LightingAppCommandDelegate.cpp +++ b/examples/lighting-app-data-mode-no-unique-id/linux/LightingAppCommandDelegate.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/examples/lighting-app/infineon/cyw30739/src/LightingManager.cpp b/examples/lighting-app/infineon/cyw30739/src/LightingManager.cpp index eb707676b5..7fd4003f36 100644 --- a/examples/lighting-app/infineon/cyw30739/src/LightingManager.cpp +++ b/examples/lighting-app/infineon/cyw30739/src/LightingManager.cpp @@ -19,7 +19,6 @@ #include "LightingManager.h" #include -#include #include using namespace chip; diff --git a/examples/lighting-app/linux/LightingAppCommandDelegate.cpp b/examples/lighting-app/linux/LightingAppCommandDelegate.cpp index cc5af976eb..c6d1cdead6 100644 --- a/examples/lighting-app/linux/LightingAppCommandDelegate.cpp +++ b/examples/lighting-app/linux/LightingAppCommandDelegate.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/src/app/AttributePathExpandIterator-Ember.cpp b/src/app/AttributePathExpandIterator-Ember.cpp index 1149f0c702..b1d6cb2a12 100644 --- a/src/app/AttributePathExpandIterator-Ember.cpp +++ b/src/app/AttributePathExpandIterator-Ember.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -98,7 +97,7 @@ void AttributePathExpandIteratorEmber::PrepareClusterIndexRange(const AttributeP } else { - mClusterIndex = emberAfClusterIndex(aEndpointId, aAttributePath.mClusterId, CLUSTER_MASK_SERVER); + mClusterIndex = emberAfClusterIndex(aEndpointId, aAttributePath.mClusterId, MATTER_CLUSTER_FLAG_SERVER); // If the given cluster id does not exist on the given endpoint, it will return uint8(0xFF), then endClusterIndex // will be 0, means we should iterate a null cluster set (skip it). mEndClusterIndex = static_cast(mClusterIndex + 1); diff --git a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp index 39b9f59d23..6874fc9f56 100644 --- a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp +++ b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/src/app/clusters/groups-server/groups-server.cpp b/src/app/clusters/groups-server/groups-server.cpp index add0261927..fe772caad1 100644 --- a/src/app/clusters/groups-server/groups-server.cpp +++ b/src/app/clusters/groups-server/groups-server.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -339,7 +338,7 @@ bool emberAfGroupsClusterRemoveAllGroupsCallback(app::CommandHandler * commandOb } iter->Release(); ScenesManagement::ScenesServer::Instance().GroupWillBeRemoved(fabricIndex, commandPath.mEndpointId, - ZCL_SCENES_GLOBAL_SCENE_GROUP_ID); + ScenesManagement::ScenesServer::kGlobalSceneGroupId); } #endif diff --git a/src/app/clusters/mode-select-server/mode-select-server.cpp b/src/app/clusters/mode-select-server/mode-select-server.cpp index 813d16d965..db771004a5 100644 --- a/src/app/clusters/mode-select-server/mode-select-server.cpp +++ b/src/app/clusters/mode-select-server/mode-select-server.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index d18aa09383..85465e085c 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -667,8 +667,9 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a if (globalSceneControl) { #ifdef MATTER_DM_PLUGIN_SCENES_MANAGEMENT - ScenesManagement::ScenesServer::Instance().StoreCurrentScene(fabric, endpoint, ZCL_SCENES_GLOBAL_SCENE_GROUP_ID, - ZCL_SCENES_GLOBAL_SCENE_SCENE_ID); + ScenesManagement::ScenesServer::Instance().StoreCurrentScene(fabric, endpoint, + ScenesManagement::ScenesServer::kGlobalSceneGroupId, + ScenesManagement::ScenesServer::kGlobalSceneId); #endif // MATTER_DM_PLUGIN_SCENES_MANAGEMENT OnOff::Attributes::GlobalSceneControl::Set(endpoint, false); } @@ -723,8 +724,8 @@ bool OnOffServer::OnWithRecallGlobalSceneCommand(app::CommandHandler * commandOb } #ifdef MATTER_DM_PLUGIN_SCENES_MANAGEMENT - ScenesManagement::ScenesServer::Instance().RecallScene(fabric, endpoint, ZCL_SCENES_GLOBAL_SCENE_GROUP_ID, - ZCL_SCENES_GLOBAL_SCENE_SCENE_ID); + ScenesManagement::ScenesServer::Instance().RecallScene(fabric, endpoint, ScenesManagement::ScenesServer::kGlobalSceneGroupId, + ScenesManagement::ScenesServer::kGlobalSceneId); #endif // MATTER_DM_PLUGIN_SCENES_MANAGEMENT OnOff::Attributes::GlobalSceneControl::Set(endpoint, true); diff --git a/src/app/clusters/scenes-server/scenes-server.h b/src/app/clusters/scenes-server/scenes-server.h index 81c7d41f65..024b6f64f6 100644 --- a/src/app/clusters/scenes-server/scenes-server.h +++ b/src/app/clusters/scenes-server/scenes-server.h @@ -40,6 +40,8 @@ class ScenesServer : public CommandHandlerInterface, public AttributeAccessInter MATTER_DM_SCENES_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; static_assert(kScenesServerMaxEndpointCount <= kEmberInvalidEndpointIndex, "Scenes endpoint count error"); static constexpr uint8_t kScenesServerMaxFabricCount = CHIP_CONFIG_MAX_FABRICS; + static constexpr SceneId kGlobalSceneId = 0x00; + static constexpr GroupId kGlobalSceneGroupId = 0x0000; // FabricSceneInfo class FabricSceneInfo diff --git a/src/app/codegen-data-model-provider/EmberMetadata.cpp b/src/app/codegen-data-model-provider/EmberMetadata.cpp index 69f9e3e889..a01b70532f 100644 --- a/src/app/codegen-data-model-provider/EmberMetadata.cpp +++ b/src/app/codegen-data-model-provider/EmberMetadata.cpp @@ -62,7 +62,7 @@ FindAttributeMetadata(const ConcreteAttributePath & aPath) return Status::UnsupportedEndpoint; } - const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, CLUSTER_MASK_SERVER); + const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, MATTER_CLUSTER_FLAG_SERVER); if (cluster == nullptr) { return Status::UnsupportedCluster; diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index 3840de9c81..ff21ae0d28 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -263,11 +263,12 @@ class ScopedMockAccessControl #define MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(zcl_type) MockAttributeId(zcl_type + 0x1000) #define MOCK_ATTRIBUTE_CONFIG_NULLABLE(zcl_type) \ - MockAttributeConfig(MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(zcl_type), zcl_type, ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_NULLABLE) + MockAttributeConfig(MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(zcl_type), zcl_type, \ + MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_NULLABLE) #define MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(zcl_type) MockAttributeId(zcl_type + 0x2000) #define MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(zcl_type) \ - MockAttributeConfig(MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(zcl_type), zcl_type, ATTRIBUTE_MASK_WRITABLE) + MockAttributeConfig(MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(zcl_type), zcl_type, MATTER_ATTRIBUTE_FLAG_WRITABLE) // clang-format off const MockNodeConfig gTestNodeConfig({ @@ -325,7 +326,7 @@ const MockNodeConfig gTestNodeConfig({ MockAttributeConfig( kReadOnlyAttributeId, ZCL_INT32U_ATTRIBUTE_TYPE, - ATTRIBUTE_MASK_NULLABLE // NOTE: explicltly NOT ATTRIBUTE_MASK_WRITABLE + MATTER_ATTRIBUTE_FLAG_NULLABLE // NOTE: explicltly NOT MATTER_ATTRIBUTE_FLAG_WRITABLE ) }), MockClusterConfig(MockClusterId(4), { @@ -481,7 +482,7 @@ const MockNodeConfig gTestNodeConfig({ // Special case handling MockAttributeConfig(kAttributeIdReadOnly, ZCL_INT32S_ATTRIBUTE_TYPE, 0), - MockAttributeConfig(kAttributeIdTimedWrite, ZCL_INT32S_ATTRIBUTE_TYPE, ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_MUST_USE_TIMED_WRITE), + MockAttributeConfig(kAttributeIdTimedWrite, ZCL_INT32S_ATTRIBUTE_TYPE, MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_MUST_USE_TIMED_WRITE), }), }), }); diff --git a/src/app/dynamic_server/DynamicDispatcher.cpp b/src/app/dynamic_server/DynamicDispatcher.cpp index e1f458f0bc..cc6ea6a1a2 100644 --- a/src/app/dynamic_server/DynamicDispatcher.cpp +++ b/src/app/dynamic_server/DynamicDispatcher.cpp @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -328,7 +329,7 @@ Optional emberAfGetServerAttributeIdByIndex(EndpointId endpoint, Cl uint8_t emberAfClusterIndex(EndpointId endpoint, ClusterId clusterId, EmberAfClusterMask mask) { - if (endpoint == kSupportedEndpoint && clusterId == OtaSoftwareUpdateProvider::Id && (mask & CLUSTER_MASK_SERVER)) + if (endpoint == kSupportedEndpoint && clusterId == OtaSoftwareUpdateProvider::Id && (mask & MATTER_CLUSTER_FLAG_SERVER)) { return 0; } @@ -352,7 +353,7 @@ const EmberAfCluster otaProviderCluster{ .attributes = nullptr, .attributeCount = 0, .clusterSize = 0, - .mask = CLUSTER_MASK_SERVER, + .mask = MATTER_CLUSTER_FLAG_SERVER, .functions = nullptr, .acceptedCommandList = acceptedCommands, .generatedCommandList = generatedCommands, diff --git a/src/app/tests/TestSceneTable.cpp b/src/app/tests/TestSceneTable.cpp index 2e541cb0e7..6f6093cd09 100644 --- a/src/app/tests/TestSceneTable.cpp +++ b/src/app/tests/TestSceneTable.cpp @@ -176,7 +176,7 @@ static EmberAfAttributeMetadata mockMetadataBool = { .attributeId = 0, .size = 1, .attributeType = ZCL_BOOLEAN_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataUint8 = { @@ -184,7 +184,7 @@ static EmberAfAttributeMetadata mockMetadataUint8 = { .attributeId = 0, .size = 1, .attributeType = ZCL_INT8U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_NULLABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_NULLABLE, }; static EmberAfAttributeMetadata mockMetadataUint8Max = { @@ -192,7 +192,7 @@ static EmberAfAttributeMetadata mockMetadataUint8Max = { .attributeId = 0, .size = 1, .attributeType = ZCL_INT8U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_NULLABLE | ATTRIBUTE_MASK_MIN_MAX, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_NULLABLE | MATTER_ATTRIBUTE_FLAG_MIN_MAX, }; static EmberAfAttributeMetadata mockMetadataUint16 = { @@ -200,7 +200,7 @@ static EmberAfAttributeMetadata mockMetadataUint16 = { .attributeId = 0, .size = 2, .attributeType = ZCL_INT16U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataUint24 = { @@ -208,7 +208,7 @@ static EmberAfAttributeMetadata mockMetadataUint24 = { .attributeId = 0, .size = 3, .attributeType = ZCL_INT24U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataUint32 = { @@ -216,7 +216,7 @@ static EmberAfAttributeMetadata mockMetadataUint32 = { .attributeId = 0, .size = 4, .attributeType = ZCL_INT32U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataUint40 = { @@ -224,7 +224,7 @@ static EmberAfAttributeMetadata mockMetadataUint40 = { .attributeId = 0, .size = 5, .attributeType = ZCL_INT40U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataUint48 = { @@ -232,7 +232,7 @@ static EmberAfAttributeMetadata mockMetadataUint48 = { .attributeId = 0, .size = 6, .attributeType = ZCL_INT48U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataUint56 = { @@ -240,7 +240,7 @@ static EmberAfAttributeMetadata mockMetadataUint56 = { .attributeId = 0, .size = 7, .attributeType = ZCL_INT56U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataUint64 = { @@ -248,7 +248,7 @@ static EmberAfAttributeMetadata mockMetadataUint64 = { .attributeId = 0, .size = 8, .attributeType = ZCL_INT64U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataInt8 = { @@ -256,7 +256,7 @@ static EmberAfAttributeMetadata mockMetadataInt8 = { .attributeId = 0, .size = 1, .attributeType = ZCL_INT8S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_MIN_MAX, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_MIN_MAX, }; static EmberAfAttributeMetadata mockMetadataInt16 = { @@ -264,7 +264,7 @@ static EmberAfAttributeMetadata mockMetadataInt16 = { .attributeId = 0, .size = 2, .attributeType = ZCL_INT16S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_MIN_MAX, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_MIN_MAX, }; static EmberAfAttributeMetadata mockMetadataInt24 = { @@ -272,7 +272,7 @@ static EmberAfAttributeMetadata mockMetadataInt24 = { .attributeId = 0, .size = 3, .attributeType = ZCL_INT24S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataInt32 = { @@ -280,7 +280,7 @@ static EmberAfAttributeMetadata mockMetadataInt32 = { .attributeId = 0, .size = 4, .attributeType = ZCL_INT32S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataInt40 = { @@ -288,7 +288,7 @@ static EmberAfAttributeMetadata mockMetadataInt40 = { .attributeId = 0, .size = 5, .attributeType = ZCL_INT40S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataInt48 = { @@ -296,7 +296,7 @@ static EmberAfAttributeMetadata mockMetadataInt48 = { .attributeId = 0, .size = 6, .attributeType = ZCL_INT48S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataInt56 = { @@ -304,7 +304,7 @@ static EmberAfAttributeMetadata mockMetadataInt56 = { .attributeId = 0, .size = 7, .attributeType = ZCL_INT56S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; static EmberAfAttributeMetadata mockMetadataInt64 = { @@ -312,7 +312,7 @@ static EmberAfAttributeMetadata mockMetadataInt64 = { .attributeId = 0, .size = 8, .attributeType = ZCL_INT64S_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE, }; // clang-format off diff --git a/src/app/util/BUILD.gn b/src/app/util/BUILD.gn index 29b3bc9563..763480f159 100644 --- a/src/app/util/BUILD.gn +++ b/src/app/util/BUILD.gn @@ -32,7 +32,6 @@ source_set("nullable-primitives") { # These headers/cpp only depend on core/common source_set("types") { sources = [ - "att-storage.h", "attribute-metadata.cpp", "attribute-metadata.h", "basic-types.h", diff --git a/src/app/util/af-types.h b/src/app/util/af-types.h index 04275a2515..dbdcaa0a46 100644 --- a/src/app/util/af-types.h +++ b/src/app/util/af-types.h @@ -23,7 +23,6 @@ * @{ */ -#include "att-storage.h" #include // For bool #include // For various uint*_t types @@ -43,11 +42,6 @@ #include #include -/** - * @brief Type for the cluster mask - */ -typedef uint8_t EmberAfClusterMask; - /** * @brief Generic function type, used for either of the cluster function. * @@ -62,6 +56,21 @@ typedef void (*EmberAfGenericClusterFunction)(void); */ #define MATTER_DM_NULL_MANUFACTURER_CODE 0x0000 +// The following define names are relevant to the ZAP_CLUSTER_MASK macro. +#define MATTER_CLUSTER_FLAG_INIT_FUNCTION 0x01 +#define MATTER_CLUSTER_FLAG_ATTRIBUTE_CHANGED_FUNCTION 0x02 +// Bit 2 (0x04) and Bit3 (0x08) are free. +#define MATTER_CLUSTER_FLAG_SHUTDOWN_FUNCTION 0x10 +#define MATTER_CLUSTER_FLAG_PRE_ATTRIBUTE_CHANGED_FUNCTION 0x20 +#define MATTER_CLUSTER_FLAG_SERVER 0x40 +#define MATTER_CLUSTER_FLAG_CLIENT 0x80 + +/** + * @brief Type for the cluster mask + * Value of the mask represents a single, or aggregated, MATTER_CLUSTER_FLAG_X + */ +typedef uint8_t EmberAfClusterMask; + /** * @brief Struct describing cluster */ @@ -119,7 +128,9 @@ struct EmberAfCluster */ uint16_t eventCount; - bool IsServer() const { return (mask & CLUSTER_MASK_SERVER) != 0; } + bool IsServer() const { return (mask & MATTER_CLUSTER_FLAG_SERVER) != 0; } + + bool IsClient() const { return (mask & MATTER_CLUSTER_FLAG_CLIENT) != 0; } }; /** @@ -232,30 +243,6 @@ struct EmberAfDefinedEndpoint chip::Span tagList; }; -// Cluster specific types - -/** - * @brief Indicates the absence of a Scene table entry. - */ -#define MATTER_DM_SCENE_TABLE_NULL_INDEX 0xFF -/** - * @brief Value used when setting or getting the endpoint in a Scene table - * entry. It indicates that the entry is not in use. - */ -#define MATTER_DM_SCENE_TABLE_UNUSED_ENDPOINT_ID 0x00 -/** - * @brief Maximum length of Scene names, not including the length byte. - */ -#define ZCL_SCENES_CLUSTER_MAXIMUM_NAME_LENGTH 16 -/** - * @brief The group identifier for the global scene. - */ -#define ZCL_SCENES_GLOBAL_SCENE_GROUP_ID 0x0000 -/** - * @brief The scene identifier for the global scene. - */ -#define ZCL_SCENES_GLOBAL_SCENE_SCENE_ID 0x00 - /** * @brief Type for referring to the tick callback for cluster. * diff --git a/src/app/util/att-storage.h b/src/app/util/att-storage.h deleted file mode 100644 index 9befaacf7c..0000000000 --- a/src/app/util/att-storage.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * Copyright (c) 2022 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 - -// Cluster masks modify how clusters are used by the framework -// -// Does this cluster have init function? -#define CLUSTER_MASK_INIT_FUNCTION (0x01) -// Does this cluster have attribute changed function? -#define CLUSTER_MASK_ATTRIBUTE_CHANGED_FUNCTION (0x02) -// Bits 0x04 and 0x08 are free. -// Does this cluster have shutdown function? -#define CLUSTER_MASK_SHUTDOWN_FUNCTION (0x10) -// Does this cluster have pre-attribute changed function? -#define CLUSTER_MASK_PRE_ATTRIBUTE_CHANGED_FUNCTION (0x20) -// Cluster is a server -#define CLUSTER_MASK_SERVER (0x40) -// Cluster is a client -#define CLUSTER_MASK_CLIENT (0x80) diff --git a/src/app/util/attribute-metadata.h b/src/app/util/attribute-metadata.h index 6703e397d5..368a90418e 100644 --- a/src/app/util/attribute-metadata.h +++ b/src/app/util/attribute-metadata.h @@ -105,23 +105,23 @@ union EmberAfDefaultOrMinMaxAttributeValue }; // Attribute masks modify how attributes are used by the framework -// +// The following define names are relevant to the ZAP_ATTRIBUTE_MASK macro. // Attribute that has this mask is NOT read-only -#define ATTRIBUTE_MASK_WRITABLE (0x01) +#define MATTER_ATTRIBUTE_FLAG_WRITABLE (0x01) // Attribute that has this mask is saved in non-volatile memory -#define ATTRIBUTE_MASK_NONVOLATILE (0x02) -// Alias until ZAP gets updated to output ATTRIBUTE_MASK_NONVOLATILE -#define ATTRIBUTE_MASK_TOKENIZE ATTRIBUTE_MASK_NONVOLATILE +#define MATTER_ATTRIBUTE_FLAG_NONVOLATILE (0x02) +// Alias until ZAP gets updated to output MATTER_ATTRIBUTE_FLAG_NONVOLATILE +#define MATTER_ATTRIBUTE_FLAG_TOKENIZE MATTER_ATTRIBUTE_FLAG_NONVOLATILE // Attribute that has this mask has a min/max values -#define ATTRIBUTE_MASK_MIN_MAX (0x04) +#define MATTER_ATTRIBUTE_FLAG_MIN_MAX (0x04) // Attribute requires a timed interaction to write -#define ATTRIBUTE_MASK_MUST_USE_TIMED_WRITE (0x08) +#define MATTER_ATTRIBUTE_FLAG_MUST_USE_TIMED_WRITE (0x08) // Attribute deferred to external storage -#define ATTRIBUTE_MASK_EXTERNAL_STORAGE (0x10) +#define MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE (0x10) // Attribute is singleton -#define ATTRIBUTE_MASK_SINGLETON (0x20) +#define MATTER_ATTRIBUTE_FLAG_SINGLETON (0x20) // Attribute is nullable -#define ATTRIBUTE_MASK_NULLABLE (0x40) +#define MATTER_ATTRIBUTE_FLAG_NULLABLE (0x40) /** * @brief Each attribute has it's metadata stored in such struct. @@ -170,41 +170,41 @@ struct EmberAfAttributeMetadata /** * Check whether this attribute has a define min and max. */ - bool HasMinMax() const { return mask & ATTRIBUTE_MASK_MIN_MAX; } + bool HasMinMax() const { return mask & MATTER_ATTRIBUTE_FLAG_MIN_MAX; } /** * Check whether this attribute is nullable. */ - bool IsNullable() const { return mask & ATTRIBUTE_MASK_NULLABLE; } + bool IsNullable() const { return mask & MATTER_ATTRIBUTE_FLAG_NULLABLE; } /** * Check whether this attribute is readonly. */ - bool IsReadOnly() const { return !(mask & ATTRIBUTE_MASK_WRITABLE); } + bool IsReadOnly() const { return !(mask & MATTER_ATTRIBUTE_FLAG_WRITABLE); } /** * Check whether this attribute requires a timed write. */ - bool MustUseTimedWrite() const { return mask & ATTRIBUTE_MASK_MUST_USE_TIMED_WRITE; } + bool MustUseTimedWrite() const { return mask & MATTER_ATTRIBUTE_FLAG_MUST_USE_TIMED_WRITE; } /** * Check whether this attibute's storage is managed outside the built-in * attribute store. */ - bool IsExternal() const { return mask & ATTRIBUTE_MASK_EXTERNAL_STORAGE; } + bool IsExternal() const { return mask & MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE; } /** * Check whether this is a "singleton" attribute, in the sense that it has a * single value across multiple instances of the cluster. This is not * mutually exclusive with the attribute being external. */ - bool IsSingleton() const { return mask & ATTRIBUTE_MASK_SINGLETON; } + bool IsSingleton() const { return mask & MATTER_ATTRIBUTE_FLAG_SINGLETON; } /** * Check whether this attribute is automatically stored in non-volatile * memory. */ - bool IsAutomaticallyPersisted() const { return (mask & ATTRIBUTE_MASK_NONVOLATILE) && !IsExternal(); } + bool IsAutomaticallyPersisted() const { return (mask & MATTER_ATTRIBUTE_FLAG_NONVOLATILE) && !IsExternal(); } }; /** @brief Returns true if the given attribute type is a string. */ diff --git a/src/app/util/attribute-storage-detail.h b/src/app/util/attribute-storage-detail.h index 922605f3f9..6972115562 100644 --- a/src/app/util/attribute-storage-detail.h +++ b/src/app/util/attribute-storage-detail.h @@ -23,7 +23,6 @@ #include #include -#include #include #include diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index 0d1b3827e8..19736e5651 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -356,7 +356,7 @@ void emAfClusterAttributeChangedCallback(const ConcreteAttributePath & attribute const EmberAfCluster * cluster = emberAfFindServerCluster(attributePath.mEndpointId, attributePath.mClusterId); if (cluster != nullptr) { - EmberAfGenericClusterFunction f = emberAfFindClusterFunction(cluster, CLUSTER_MASK_ATTRIBUTE_CHANGED_FUNCTION); + EmberAfGenericClusterFunction f = emberAfFindClusterFunction(cluster, MATTER_CLUSTER_FLAG_ATTRIBUTE_CHANGED_FUNCTION); if (f != nullptr) { ((EmberAfClusterAttributeChangedCallback) f)(attributePath); @@ -382,7 +382,7 @@ Status emAfClusterPreAttributeChangedCallback(const ConcreteAttributePath & attr // Casting and calling a function pointer on the same line results in ignoring the return // of the call on gcc-arm-none-eabi-9-2019-q4-major EmberAfClusterPreAttributeChangedCallback f = (EmberAfClusterPreAttributeChangedCallback) (emberAfFindClusterFunction( - cluster, CLUSTER_MASK_PRE_ATTRIBUTE_CHANGED_FUNCTION)); + cluster, MATTER_CLUSTER_FLAG_PRE_ATTRIBUTE_CHANGED_FUNCTION)); if (f != nullptr) { status = f(attributePath, attributeType, size, value); @@ -399,7 +399,7 @@ static void initializeEndpoint(EmberAfDefinedEndpoint * definedEndpoint) const EmberAfCluster * cluster = &(epType->cluster[clusterIndex]); EmberAfGenericClusterFunction f; emberAfClusterInitCallback(definedEndpoint->endpoint, cluster->clusterId); - f = emberAfFindClusterFunction(cluster, CLUSTER_MASK_INIT_FUNCTION); + f = emberAfFindClusterFunction(cluster, MATTER_CLUSTER_FLAG_INIT_FUNCTION); if (f != nullptr) { ((EmberAfInitFunction) f)(definedEndpoint->endpoint); @@ -415,7 +415,7 @@ static void shutdownEndpoint(EmberAfDefinedEndpoint * definedEndpoint) for (clusterIndex = 0; clusterIndex < epType->clusterCount; clusterIndex++) { const EmberAfCluster * cluster = &(epType->cluster[clusterIndex]); - EmberAfGenericClusterFunction f = emberAfFindClusterFunction(cluster, CLUSTER_MASK_SHUTDOWN_FUNCTION); + EmberAfGenericClusterFunction f = emberAfFindClusterFunction(cluster, MATTER_CLUSTER_FLAG_SHUTDOWN_FUNCTION); if (f != nullptr) { ((EmberAfShutdownFunction) f)(definedEndpoint->endpoint); @@ -539,7 +539,7 @@ static Status typeSensitiveMemCopy(ClusterId clusterId, uint8_t * dest, uint8_t */ bool emAfMatchCluster(const EmberAfCluster * cluster, const EmberAfAttributeSearchRecord * attRecord) { - return (cluster->clusterId == attRecord->clusterId && (cluster->mask & CLUSTER_MASK_SERVER)); + return (cluster->clusterId == attRecord->clusterId && (cluster->mask & MATTER_CLUSTER_FLAG_SERVER)); } /** @@ -607,8 +607,8 @@ Status emAfReadOrWriteAttribute(const EmberAfAttributeSearchRecord * attRecord, { uint8_t * attributeLocation = - (am->mask & ATTRIBUTE_MASK_SINGLETON ? singletonAttributeLocation(am) - : attributeData + attributeOffsetIndex); + (am->mask & MATTER_ATTRIBUTE_FLAG_SINGLETON ? singletonAttributeLocation(am) + : attributeData + attributeOffsetIndex); uint8_t *src, *dst; if (write) { @@ -637,7 +637,7 @@ Status emAfReadOrWriteAttribute(const EmberAfAttributeSearchRecord * attRecord, } // Is the attribute externally stored? - if (am->mask & ATTRIBUTE_MASK_EXTERNAL_STORAGE) + if (am->mask & MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE) { return (write ? emberAfExternalAttributeWriteCallback(attRecord->endpoint, attRecord->clusterId, am, buffer) @@ -657,7 +657,8 @@ Status emAfReadOrWriteAttribute(const EmberAfAttributeSearchRecord * attRecord, else { // Not the attribute we are looking for // Increase the index if attribute is not externally stored - if (!(am->mask & ATTRIBUTE_MASK_EXTERNAL_STORAGE) && !(am->mask & ATTRIBUTE_MASK_SINGLETON)) + if (!(am->mask & MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE) && + !(am->mask & MATTER_ATTRIBUTE_FLAG_SINGLETON)) { attributeOffsetIndex = static_cast(attributeOffsetIndex + emberAfAttributeSize(am)); } @@ -759,7 +760,7 @@ bool emberAfContainsClient(EndpointId endpoint, ClusterId clusterId) return false; } - return (emberAfFindClusterInType(emAfEndpoints[ep].endpointType, clusterId, CLUSTER_MASK_CLIENT) != nullptr); + return (emberAfFindClusterInType(emAfEndpoints[ep].endpointType, clusterId, MATTER_CLUSTER_FLAG_CLIENT) != nullptr); } // This will find the first server that has the clusterId given from the index of endpoint. @@ -770,7 +771,7 @@ bool emberAfContainsServerFromIndex(uint16_t index, ClusterId clusterId) return false; } - return emberAfFindClusterInType(emAfEndpoints[index].endpointType, clusterId, CLUSTER_MASK_SERVER); + return emberAfFindClusterInType(emAfEndpoints[index].endpointType, clusterId, MATTER_CLUSTER_FLAG_SERVER); } namespace chip { @@ -822,7 +823,7 @@ const EmberAfCluster * emberAfFindServerCluster(EndpointId endpoint, ClusterId c return nullptr; } - return emberAfFindClusterInType(emAfEndpoints[ep].endpointType, clusterId, CLUSTER_MASK_SERVER); + return emberAfFindClusterInType(emAfEndpoints[ep].endpointType, clusterId, MATTER_CLUSTER_FLAG_SERVER); } // Returns cluster within the endpoint; Does not ignore disabled endpoints @@ -848,7 +849,7 @@ uint16_t emberAfGetClusterServerEndpointIndex(EndpointId endpoint, ClusterId clu return kEmberInvalidEndpointIndex; } - if (emberAfFindClusterInType(emAfEndpoints[epIndex].endpointType, cluster, CLUSTER_MASK_SERVER) == nullptr) + if (emberAfFindClusterInType(emAfEndpoints[epIndex].endpointType, cluster, MATTER_CLUSTER_FLAG_SERVER) == nullptr) { // The provided endpoint does not contain the given cluster server. return kEmberInvalidEndpointIndex; @@ -864,7 +865,7 @@ uint16_t emberAfGetClusterServerEndpointIndex(EndpointId endpoint, ClusterId clu // Increase adjustedEndpointIndex for every endpoint containing the cluster server // before our endpoint of interest if (emAfEndpoints[i].endpoint != kInvalidEndpointId && - (emberAfFindClusterInType(emAfEndpoints[i].endpointType, cluster, CLUSTER_MASK_SERVER) != nullptr)) + (emberAfFindClusterInType(emAfEndpoints[i].endpointType, cluster, MATTER_CLUSTER_FLAG_SERVER) != nullptr)) { adjustedEndpointIndex++; } @@ -989,7 +990,7 @@ uint8_t emberAfClusterCountByIndex(uint16_t endpointIndex, bool server) uint8_t emberAfClusterCountForEndpointType(const EmberAfEndpointType * type, bool server) { - const EmberAfClusterMask cluster_mask = server ? CLUSTER_MASK_SERVER : CLUSTER_MASK_CLIENT; + const EmberAfClusterMask cluster_mask = server ? MATTER_CLUSTER_FLAG_SERVER : MATTER_CLUSTER_FLAG_CLIENT; return static_cast(std::count_if(type->cluster, type->cluster + type->clusterCount, [=](const EmberAfCluster & cluster) { return (cluster.mask & cluster_mask) != 0; })); @@ -1070,7 +1071,7 @@ const EmberAfCluster * emberAfGetNthCluster(EndpointId endpoint, uint8_t n, bool } const EmberAfEndpointType * endpointType = emAfEndpoints[index].endpointType; - const EmberAfClusterMask cluster_mask = server ? CLUSTER_MASK_SERVER : CLUSTER_MASK_CLIENT; + const EmberAfClusterMask cluster_mask = server ? MATTER_CLUSTER_FLAG_SERVER : MATTER_CLUSTER_FLAG_CLIENT; const uint8_t clusterCount = endpointType->clusterCount; uint8_t c = 0; @@ -1212,7 +1213,7 @@ void emAfLoadAttributeDefaults(EndpointId endpoint, Optional clusterI size_t defaultValueSizeForBigEndianNudger = 0; // Bypasses compiler warning about unused variable for little endian platforms. (void) defaultValueSizeForBigEndianNudger; - if ((am->mask & ATTRIBUTE_MASK_MIN_MAX) != 0U) + if ((am->mask & MATTER_ATTRIBUTE_FLAG_MIN_MAX) != 0U) { // This is intentionally 2 and not 4 bytes since defaultValue in min/max // attributes is still uint16_t. @@ -1454,7 +1455,8 @@ DataVersion * emberAfDataVersionStorage(const ConcreteClusterPath & aConcreteClu // This does a second walk over endpoints to find the right one, but // probably worth it to avoid duplicating code. - auto clusterIndex = emberAfClusterIndex(aConcreteClusterPath.mEndpointId, aConcreteClusterPath.mClusterId, CLUSTER_MASK_SERVER); + auto clusterIndex = + emberAfClusterIndex(aConcreteClusterPath.mEndpointId, aConcreteClusterPath.mClusterId, MATTER_CLUSTER_FLAG_SERVER); if (clusterIndex == 0xFF) { // No such cluster on this endpoint. diff --git a/src/app/util/attribute-storage.h b/src/app/util/attribute-storage.h index 9d2dcc60bb..3b8a2e3fb9 100644 --- a/src/app/util/attribute-storage.h +++ b/src/app/util/attribute-storage.h @@ -18,7 +18,6 @@ #pragma once #include -#include #include #include #include @@ -60,12 +59,12 @@ static constexpr uint16_t kEmberInvalidEndpointIndex = 0xFFFF; } /* cluster revision */ \ } -// The attrMask must contain the relevant ATTRIBUTE_MASK_* bits from +// The attrMask must contain the relevant MATTER_ATTRIBUTE_FLAG_* bits from // attribute-metadata.h. Specifically: // -// * Writable attributes must have ATTRIBUTE_MASK_WRITABLE -// * Nullable attributes (have X in the quality column in the spec) must have ATTRIBUTE_MASK_NULLABLE -// * Attributes that have T in the Access column in the spec must have ATTRIBUTE_MASK_MUST_USE_TIMED_WRITE +// * Writable attributes must have MATTER_ATTRIBUTE_FLAG_WRITABLE +// * Nullable attributes (have X in the quality column in the spec) must have MATTER_ATTRIBUTE_FLAG_NULLABLE +// * Attributes that have T in the Access column in the spec must have MATTER_ATTRIBUTE_FLAG_MUST_USE_TIMED_WRITE #define DECLARE_DYNAMIC_ATTRIBUTE(attId, attType, attSizeBytes, attrMask) \ { \ ZAP_EMPTY_DEFAULT(), attId, attSizeBytes, ZAP_TYPE(attType), attrMask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) \ @@ -223,8 +222,8 @@ uint8_t emberAfGetClusterCountForEndpoint(chip::EndpointId endpoint); // Check if a cluster is implemented or not. If yes, the cluster is returned. // // mask = 0 -> find either client or server -// mask = CLUSTER_MASK_CLIENT -> find client -// mask = CLUSTER_MASK_SERVER -> find server +// mask = MATTER_CLUSTER_FLAG_CLIENT -> find client +// mask = MATTER_CLUSTER_FLAG_SERVER -> find server // // If a pointer to an index is provided, it will be updated to point to the relative index of the cluster // within the set of clusters that match the mask criteria. diff --git a/src/app/util/attribute-table.cpp b/src/app/util/attribute-table.cpp index 0d68701b63..b84104d42a 100644 --- a/src/app/util/attribute-table.cpp +++ b/src/app/util/attribute-table.cpp @@ -365,7 +365,7 @@ Status emAfWriteAttribute(const ConcreteAttributePath & path, const EmberAfWrite // if the value the attribute is being set to is out of range // return Status::ConstraintError - if ((metadata->mask & ATTRIBUTE_MASK_MIN_MAX) != 0U) + if ((metadata->mask & MATTER_ATTRIBUTE_FLAG_MIN_MAX) != 0U) { EmberAfDefaultAttributeValue minv = metadata->defaultValue.ptrToMinMaxValue->minValue; EmberAfDefaultAttributeValue maxv = metadata->defaultValue.ptrToMinMaxValue->maxValue; diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 0ea63cba30..af336dd39f 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -95,7 +94,7 @@ Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCom return Status::UnsupportedEndpoint; } - const EmberAfCluster * cluster = emberAfFindClusterInType(type, aCommandPath.mClusterId, CLUSTER_MASK_SERVER); + const EmberAfCluster * cluster = emberAfFindClusterInType(type, aCommandPath.mClusterId, MATTER_CLUSTER_FLAG_SERVER); if (cluster == nullptr) { return Status::UnsupportedCluster; @@ -223,7 +222,7 @@ Protocols::InteractionModel::Status UnsupportedAttributeStatus(const ConcreteAtt return Status::UnsupportedEndpoint; } - const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, CLUSTER_MASK_SERVER); + const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, MATTER_CLUSTER_FLAG_SERVER); if (cluster == nullptr) { return Status::UnsupportedCluster; @@ -800,7 +799,7 @@ Protocols::InteractionModel::Status CheckEventSupportStatus(const ConcreteEventP return Status::UnsupportedEndpoint; } - const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, CLUSTER_MASK_SERVER); + const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, MATTER_CLUSTER_FLAG_SERVER); if (cluster == nullptr) { return Status::UnsupportedCluster; diff --git a/src/app/util/endpoint-config-defines.h b/src/app/util/endpoint-config-defines.h index 2a54c5d581..7da14edc50 100644 --- a/src/app/util/endpoint-config-defines.h +++ b/src/app/util/endpoint-config-defines.h @@ -29,5 +29,5 @@ { \ (uint32_t) x \ } -#define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask -#define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask +#define ZAP_ATTRIBUTE_MASK(mask) MATTER_ATTRIBUTE_FLAG_##mask +#define ZAP_CLUSTER_MASK(bit) MATTER_CLUSTER_FLAG_##bit diff --git a/src/app/util/mock/MockNodeConfig.cpp b/src/app/util/mock/MockNodeConfig.cpp index c6572ed0ae..a643daefad 100644 --- a/src/app/util/mock/MockNodeConfig.cpp +++ b/src/app/util/mock/MockNodeConfig.cpp @@ -19,7 +19,6 @@ #include "app/util/af-types.h" #include -#include #include #include #include @@ -127,9 +126,10 @@ MockClusterConfig::MockClusterConfig(ClusterId aId, std::initializer_list(attributes.size()); - mEmberCluster.mask = CLUSTER_MASK_SERVER; + mEmberCluster.mask = MATTER_CLUSTER_FLAG_SERVER; mEmberCluster.eventCount = static_cast(mEmberEventList.size()); mEmberCluster.eventList = mEmberEventList.data(); diff --git a/src/app/util/mock/MockNodeConfig.h b/src/app/util/mock/MockNodeConfig.h index 39f11052a7..6510a0e1a1 100644 --- a/src/app/util/mock/MockNodeConfig.h +++ b/src/app/util/mock/MockNodeConfig.h @@ -44,7 +44,7 @@ constexpr EmberAfAttributeMetadata DefaultAttributeMetadata(chip::AttributeId id .attributeId = id, .size = 4, .attributeType = ZCL_INT32U_ATTRIBUTE_TYPE, - .mask = ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_NULLABLE, + .mask = MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_NULLABLE, }; } @@ -55,7 +55,7 @@ struct MockAttributeConfig MockAttributeConfig(AttributeId aId) : id(aId), attributeMetaData(internal::DefaultAttributeMetadata(aId)) {} MockAttributeConfig(AttributeId aId, EmberAfAttributeMetadata metadata) : id(aId), attributeMetaData(metadata) {} MockAttributeConfig(AttributeId aId, EmberAfAttributeType type, - EmberAfAttributeMask mask = ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_NULLABLE) : + EmberAfAttributeMask mask = MATTER_ATTRIBUTE_FLAG_WRITABLE | MATTER_ATTRIBUTE_FLAG_NULLABLE) : id(aId), attributeMetaData(internal::DefaultAttributeMetadata(aId)) { diff --git a/src/app/util/mock/attribute-storage.cpp b/src/app/util/mock/attribute-storage.cpp index 256d0a3a88..d0843d89cb 100644 --- a/src/app/util/mock/attribute-storage.cpp +++ b/src/app/util/mock/attribute-storage.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -272,7 +271,7 @@ chip::Optional emberAfGetServerAttributeIdByIndex(chip::Endpo uint8_t emberAfClusterIndex(chip::EndpointId endpointId, chip::ClusterId clusterId, EmberAfClusterMask mask) { - VerifyOrReturnValue(mask == 0 || (mask & CLUSTER_MASK_SERVER) != 0, UINT8_MAX); // only server clusters supported + VerifyOrReturnValue(mask == 0 || (mask & MATTER_CLUSTER_FLAG_SERVER) != 0, UINT8_MAX); // only server clusters supported ptrdiff_t index; auto cluster = GetMockNodeConfig().clusterByIds(endpointId, clusterId, &index); VerifyOrReturnValue(cluster != nullptr, UINT8_MAX); diff --git a/src/controller/tests/TestWriteChunking.cpp b/src/controller/tests/TestWriteChunking.cpp index 5bb7ef9521..fadba53dfe 100644 --- a/src/controller/tests/TestWriteChunking.cpp +++ b/src/controller/tests/TestWriteChunking.cpp @@ -97,8 +97,8 @@ class TestWriteChunking : public Test::AppContext //clang-format off DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(testClusterAttrsOnEndpoint) -DECLARE_DYNAMIC_ATTRIBUTE(kTestListAttribute, ARRAY, 1, ATTRIBUTE_MASK_WRITABLE), - DECLARE_DYNAMIC_ATTRIBUTE(kTestListAttribute2, ARRAY, 1, ATTRIBUTE_MASK_WRITABLE), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); +DECLARE_DYNAMIC_ATTRIBUTE(kTestListAttribute, ARRAY, 1, MATTER_ATTRIBUTE_FLAG_WRITABLE), + DECLARE_DYNAMIC_ATTRIBUTE(kTestListAttribute2, ARRAY, 1, MATTER_ATTRIBUTE_FLAG_WRITABLE), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(testEndpointClusters) DECLARE_DYNAMIC_CLUSTER(Clusters::UnitTesting::Id, testClusterAttrsOnEndpoint, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRIMDispatch.mm b/src/darwin/Framework/CHIP/ServerEndpoint/MTRIMDispatch.mm index d21242956b..b283c8b819 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRIMDispatch.mm +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRIMDispatch.mm @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm index e2f6fecbbb..2927efa181 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm @@ -312,7 +312,7 @@ - (BOOL)associateWithController:(nullable MTRDeviceController *)controller // Size in bytes does not matter, since we plan to // handle this entirely via AttributeAccessInterface. 0, - // ATTRIBUTE_MASK_NULLABLE is not relevant because we + // MATTER_ATTRIBUTE_FLAG_NULLABLE is not relevant because we // are handling this all via AttributeAccessInterface. 0))); } diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm index 1b0f27fbaf..8e238d31e5 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm @@ -27,11 +27,10 @@ #include #include -// TODO: These af-types.h and att-storage.h and attribute-storage.h and +// TODO: These af-types.h and attribute-storage.h and // endpoint-config-api.h and probably CodeUtils.h bits are a hack that should // eventually go away. #include -#include #include #include #include @@ -257,7 +256,7 @@ - (BOOL)finishAssociationWithController:(nullable MTRDeviceController *)controll metadata.clusterSize = 0; // All our attributes are external. - metadata.mask = CLUSTER_MASK_SERVER; + metadata.mask = MATTER_CLUSTER_FLAG_SERVER; metadata.functions = nullptr; // None of our clusters, including Descriptor, uses these. @@ -278,7 +277,7 @@ - (BOOL)finishAssociationWithController:(nullable MTRDeviceController *)controll metadata.clusterSize = 0; // All our attributes are external. - metadata.mask = CLUSTER_MASK_SERVER; + metadata.mask = MATTER_CLUSTER_FLAG_SERVER; metadata.functions = nullptr; // Descriptor does not use these. diff --git a/src/data-model-providers/codegen/tests/TestEmberAttributeDataBuffer.cpp b/src/data-model-providers/codegen/tests/TestEmberAttributeDataBuffer.cpp new file mode 100644 index 0000000000..3d9571817a --- /dev/null +++ b/src/data-model-providers/codegen/tests/TestEmberAttributeDataBuffer.cpp @@ -0,0 +1,1179 @@ +/* + * 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 + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace chip; +using namespace chip::app; + +namespace { + +/// encodes a simple value in a TLV buffer +class TLVEncodedValue +{ +public: + TLVEncodedValue() = default; + ~TLVEncodedValue() = default; + + template + TLV::TLVReader EncodeValue(const T & value) + { + const auto kTag = TLV::ContextTag(AttributeDataIB::Tag::kData); + + TLV::TLVWriter writer; + writer.Init(mBuffer, sizeof(mBuffer)); + + TLV::TLVType outer; + + VerifyOrDie(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer) == CHIP_NO_ERROR); + VerifyOrDie(DataModel::Encode(writer, kTag, value) == CHIP_NO_ERROR); + VerifyOrDie(writer.EndContainer(outer) == CHIP_NO_ERROR); + + VerifyOrDie(writer.Finalize() == CHIP_NO_ERROR); + size_t fill = writer.GetLengthWritten(); + + TLV::TLVReader reader; + reader.Init(mBuffer, fill); + VerifyOrDie(reader.Next() == CHIP_NO_ERROR); + VerifyOrDie(reader.GetTag() == TLV::AnonymousTag()); + VerifyOrDie(reader.EnterContainer(outer) == CHIP_NO_ERROR); + VerifyOrDie(reader.Next() == CHIP_NO_ERROR); + VerifyOrDie(reader.GetTag() == kTag); + + return reader; + } + +private: + static constexpr size_t kMaxSize = 128; + uint8_t mBuffer[kMaxSize]; +}; + +class EncodeResult +{ +public: + explicit EncodeResult() = default; + EncodeResult(CHIP_ERROR error) : mResult(error) { VerifyOrDie(error != CHIP_NO_ERROR); } + + static EncodeResult Ok() { return EncodeResult(); } + + bool IsSuccess() const { return !mResult.has_value(); } + + bool operator==(const CHIP_ERROR & other) const { return mResult.has_value() && (*mResult == other); } + + const std::optional & Value() const { return mResult; } + +private: + std::optional mResult; +}; + +template +bool IsEqual(const T & a, const T & b) +{ + return a == b; +} + +template <> +bool IsEqual(const float & a, const float & b) +{ + if (std::isnan(a) && std::isnan(b)) + { + return true; + } + + return a == b; +} + +template <> +bool IsEqual(const double & a, const double & b) +{ + if (std::isnan(a) && std::isnan(b)) + { + return true; + } + + return a == b; +} + +template <> +bool IsEqual(const ByteSpan & a, const ByteSpan & b) +{ + return a.data_equal(b); +} + +template <> +bool IsEqual(const CharSpan & a, const CharSpan & b) +{ + return a.data_equal(b); +} + +template +bool IsEqual(const std::optional & a, const std::optional & b) +{ + if (a.has_value() != b.has_value()) + { + return false; + } + + if (!a.has_value()) + { + return true; + } + + return IsEqual(*a, *b); +} + +template +bool IsEqual(const DataModel::Nullable & a, const DataModel::Nullable & b) +{ + if (a.IsNull() != b.IsNull()) + { + return false; + } + + if (a.IsNull()) + { + return true; + } + + return IsEqual(a.Value(), b.Value()); +} + +/// Validates that an encoded value in ember takes a specific format +template +class EncodeTester +{ +public: + EncodeTester(const EmberAfAttributeMetadata * meta) : mMetaData(meta) {} + ~EncodeTester() = default; + + template + EncodeResult TryEncode(const T & value, const uint8_t (&arr)[N]) + { + ByteSpan expected(arr); + MutableByteSpan out_span(mEmberAttributeDataBuffer); + Ember::EmberAttributeDataBuffer buffer(mMetaData, out_span); + + TLVEncodedValue tlvEncoded; + TLV::TLVReader reader = tlvEncoded.EncodeValue(value); + + CHIP_ERROR err = buffer.Decode(reader); + if (err != CHIP_NO_ERROR) + { + return err; + } + + if (expected.size() != out_span.size()) + { + ChipLogError(Test, "Decode mismatch in size: expected %u, got %u", static_cast(expected.size()), + static_cast(out_span.size())); + return CHIP_ERROR_INTERNAL; + } + + if (!expected.data_equal(out_span)) + { + ChipLogError(Test, "Decode mismatch in content for %u bytes", static_cast(expected.size())); + return CHIP_ERROR_INTERNAL; + } + + return EncodeResult::Ok(); + } + + template + EncodeResult TryDecode(const T & value, const uint8_t (&arr)[N]) + { + // Write data to TLV + { + uint8_t mutableBuffer[N]; + memcpy(mutableBuffer, arr, N); + + MutableByteSpan data_span(mutableBuffer); + Ember::EmberAttributeDataBuffer buffer(mMetaData, data_span); + + TLV::TLVWriter writer; + writer.Init(mEmberAttributeDataBuffer, sizeof(mEmberAttributeDataBuffer)); + ReturnErrorOnFailure(buffer.Encode(writer, TLV::AnonymousTag())); + ReturnErrorOnFailure(writer.Finalize()); + } + + // Data was written in TLV. Take it back out + + TLV::TLVReader reader; + reader.Init(mEmberAttributeDataBuffer, sizeof(mEmberAttributeDataBuffer)); + + ReturnErrorOnFailure(reader.Next()); + + T encodedValue; + ReturnErrorOnFailure(DataModel::Decode(reader, encodedValue)); + + if (!IsEqual(encodedValue, value)) + { + ChipLogError(Test, "Encode mismatch: different data"); + return CHIP_ERROR_INTERNAL; + } + + return EncodeResult::Ok(); + } + +private: + const EmberAfAttributeMetadata * mMetaData; + uint8_t mEmberAttributeDataBuffer[kMaxSize]; +}; + +const EmberAfAttributeMetadata * CreateFakeMeta(EmberAfAttributeType type, bool nullable) +{ + static EmberAfAttributeMetadata meta = { + .defaultValue = EmberAfDefaultOrMinMaxAttributeValue(static_cast(nullptr)), + .attributeId = 0, + .size = 0, // likely not valid, however not used for tests + .attributeType = ZCL_UNKNOWN_ATTRIBUTE_TYPE, + .mask = 0, + }; + + meta.attributeType = type; + meta.mask = nullable ? MATTER_ATTRIBUTE_FLAG_NULLABLE : 0; + + return &meta; +} + +} // namespace + +// All the tests below assume buffer ordering in little endian format +// Since currently all chip platforms in CI are little endian, we just kept tests +// as-is +static_assert(!CHIP_CONFIG_BIG_ENDIAN_TARGET); + +TEST(TestEmberAttributeBuffer, TestEncodeUnsignedTypes) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8U_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xFD, { 0xFD }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(255, { 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8U_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xFD, { 0xFD }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + + // Not allowed to encode null-equivalent + EXPECT_EQ(tester.TryEncode(0xFF, { 0xFF }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT16U_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xFD, { 0xFD, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(255, { 0xFF, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xABCD, { 0xCD, 0xAB }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xFFFF, { 0xFF, 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT16U_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xFD, { 0xFD, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(255, { 0xFF, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xABCD, { 0xCD, 0xAB }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + + // Not allowed to encode null-equivalent + EXPECT_EQ(tester.TryEncode(0xFFFF, { 0xFF, 0xFF }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64U_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0, 0, 0, 0, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x1234567, { 0x67, 0x45, 0x23, 0x01, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xAABBCCDDEEFF1122, { 0x22, 0x11, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA }).IsSuccess()); + EXPECT_TRUE( + tester.TryEncode(std::numeric_limits::max() - 1, { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }) + .IsSuccess()); + + EXPECT_TRUE(tester + .TryEncode>(DataModel::NullNullable, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }) + .IsSuccess()); + + EXPECT_EQ( + tester.TryEncode(std::numeric_limits::max(), { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }), + CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64U_ATTRIBUTE_TYPE, false /* nullable */)); + + // we should be able to encode the maximum value + EXPECT_TRUE( + tester.TryEncode(std::numeric_limits::max(), { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }) + .IsSuccess()); + } + + /// Odd sized integers + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24U_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryEncode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0xFFFFFF, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + + // Out of range + EXPECT_EQ(tester.TryEncode(0x1000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + EXPECT_EQ(tester.TryEncode(0xFF000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + + // Out of range + EXPECT_EQ(tester.TryEncode(0x1000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + // cannot encode null equivalent value + EXPECT_EQ(tester.TryEncode(0xFFFFFF, { 0x56, 0x34, 0x12 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT40U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(0, { 0, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x123456, { 0x56, 0x34, 0x12, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x123456FFFF, { 0xFF, 0xFF, 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE( + tester.TryEncode>(DataModel::NullNullable, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + + // Out of range + EXPECT_EQ(tester.TryEncode(0x10011001100, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + // cannot encode null equivalent value + EXPECT_EQ(tester.TryEncode(0xFFFFFFFFFF, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + + // Double-check tests, not as exhaustive, to cover all other unsigned values and get + // more test line coverage + { + EncodeTester tester(CreateFakeMeta(ZCL_INT32U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(0x1234, { 0x34, 0x12, 0, 0 }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT48U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(0x1234, { 0x34, 0x12, 0, 0, 0, 0 }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT56U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(0x1234, { 0x34, 0x12, 0, 0, 0, 0, 0 }).IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestEncodeSignedTypes) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8S_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(127, { 127 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-10, { 0xF6 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-128, { 0x80 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8S_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(127, { 127 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-10, { 0xF6 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-127, { 0x81 }).IsSuccess()); + + // NULL canot be encoded + EXPECT_EQ(tester.TryEncode(std::numeric_limits::min(), { 0x80 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + { + + EncodeTester tester(CreateFakeMeta(ZCL_INT16S_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(127, { 127, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-10, { 0xF6, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-128, { 0x80, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(std::numeric_limits::min(), { 0x0, 0x80 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT16S_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(127, { 127, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-10, { 0xF6, 0xFF }).IsSuccess()); + + // NULL canot be encoded + EXPECT_EQ(tester.TryEncode(std::numeric_limits::min(), { 0x80 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + + // Odd size integers + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24S_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-1, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-10, { 0xF6, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF }).IsSuccess()); + + // Out of range + EXPECT_EQ(tester.TryEncode(0x1000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + EXPECT_EQ(tester.TryEncode(0x0F000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + EXPECT_EQ(tester.TryEncode(-0x1000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24S_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-1, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-10, { 0xF6, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF }).IsSuccess()); + + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0x00, 0x00, 0x80 }).IsSuccess()); + + // Out of range + EXPECT_EQ(tester.TryEncode(0x1000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + // cannot encode null equivalent value - this is the minimum negative value + // for 24-bit + EXPECT_EQ(tester.TryEncode(-(1 << 24) - 1, { 0x56, 0x34, 0x12 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + + // Out of range for signed - these are unsigned values that are larger + EXPECT_EQ(tester.TryEncode(0xFFFFFF, { 0x56, 0x34, 0x12 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + EXPECT_EQ(tester.TryEncode(0x800000, { 0x56, 0x34, 0x12 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT40S_ATTRIBUTE_TYPE, true /* nullable */)); + + // NOTE: to generate encoded values, you an use commands like: + // + // python -c 'import struct; print(", ".join(["0x%X" % v for v in struct.pack("(0, { 0, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(0x123456, { 0x56, 0x34, 0x12, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-123456789, { 0xeb, 0x32, 0xa4, 0xf8, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(-12345678910, { 0xc2, 0xe3, 0x23, 0x20, 0xfd }).IsSuccess()); + + EXPECT_TRUE( + tester.TryEncode>(DataModel::NullNullable, { 0x00, 0x00, 0x00, 0x00, 0x80 }).IsSuccess()); + + // Out of range + EXPECT_EQ(tester.TryEncode(0x10011001100, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + // cannot encode null equivalent value + EXPECT_EQ(tester.TryEncode(-(1LL << 40) - 1, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + // negative out of range + EXPECT_EQ(tester.TryEncode(-0x10000000000, { 0 }), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + + // Double-check tests, not as exhaustive, to cover all other unsigned values and get + // more test line coverage + { + EncodeTester tester(CreateFakeMeta(ZCL_INT32S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT48S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT56S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + + // min/max ranges too + EXPECT_TRUE( + tester.TryEncode(std::numeric_limits::min() + 1, { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }) + .IsSuccess()); + EXPECT_TRUE( + tester.TryEncode(std::numeric_limits::max(), { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }) + .IsSuccess()); + + // Reserved value for NULL + EXPECT_EQ( + tester.TryEncode(std::numeric_limits::min(), { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }), + CHIP_IM_GLOBAL_STATUS(ConstraintError)); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64S_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryEncode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + + EXPECT_TRUE( + tester.TryEncode(std::numeric_limits::min(), { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }) + .IsSuccess()); + EXPECT_TRUE( + tester.TryEncode(std::numeric_limits::min() + 1, { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }) + .IsSuccess()); + EXPECT_TRUE( + tester.TryEncode(std::numeric_limits::max(), { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }) + .IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestEncodeBool) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(true, { 1 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(false, { 0 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryEncode(true, { 1 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(false, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestEncodeFloatingPoint) +{ + // NOTE: to generate encoded values, you an use commands like: + // + // python -c 'import struct; print(", ".join(["0x%X" % v for v in struct.pack("(123.55f, { 0x9A, 0x19, 0xF7, 0x42 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_SINGLE_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(123.55f, { 0x9A, 0x19, 0xF7, 0x42 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0, 0, 0xC0, 0x7F }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryEncode(123.55, { 0x33, 0x33, 0x33, 0x33, 0x33, 0xE3, 0x5E, 0x40 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(123.55, { 0x33, 0x33, 0x33, 0x33, 0x33, 0xE3, 0x5E, 0x40 }).IsSuccess()); + EXPECT_TRUE( + tester.TryEncode>(DataModel::NullNullable, { 0, 0, 0, 0, 0, 0, 0xF8, 0x7F }).IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestEncodeStrings) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_CHAR_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryEncode(""_span, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode("test"_span, { 4, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode("foo"_span, { 3, 'f', 'o', 'o' }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(""_span, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode("test"_span, { 4, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryEncode(""_span, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode("test"_span, { 4, 0, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode("foo"_span, { 3, 0, 'f', 'o', 'o' }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode("test"_span, { 4, 0, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + } + + const uint8_t kOctetData[] = { 1, 2, 3 }; + + // Binary data + { + EncodeTester tester(CreateFakeMeta(ZCL_OCTET_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryEncode(ByteSpan({}), { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(ByteSpan(kOctetData), { 3, 1, 2, 3 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_OCTET_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(ByteSpan({}), { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(ByteSpan(kOctetData), { 3, 1, 2, 3 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryEncode(ByteSpan({}), { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(ByteSpan(kOctetData), { 3, 0, 1, 2, 3 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryEncode(ByteSpan({}), { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode(ByteSpan(kOctetData), { 3, 0, 1, 2, 3 }).IsSuccess()); + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestEncodeFailures) +{ + { + // attribute type that is not handled + EncodeTester tester(CreateFakeMeta(ZCL_UNKNOWN_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_EQ(tester.TryEncode>(DataModel::NullNullable, { 0 }), CHIP_IM_GLOBAL_STATUS(Failure)); + } + + { + // Insufficient space + EncodeTester<3> tester(CreateFakeMeta(ZCL_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + + // Empty is ok + EXPECT_TRUE(tester.TryEncode(""_span, { 0 }).IsSuccess()); + + // Short strings (with and without count) is wrong. + EXPECT_EQ(tester.TryEncode("test"_span, { 0 }), CHIP_ERROR_NO_MEMORY); + EXPECT_EQ(tester.TryEncode("foo"_span, { 3, 'f', 'o' }), CHIP_ERROR_NO_MEMORY); + + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } + + { + // Insufficient space + EncodeTester<3> tester(CreateFakeMeta(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + + // Empty is ok + EXPECT_TRUE(tester.TryEncode(""_span, { 0, 0 }).IsSuccess()); + + // Short strings (with and without count) is wrong. + EXPECT_EQ(tester.TryEncode("test"_span, { 0 }), CHIP_ERROR_NO_MEMORY); + EXPECT_EQ(tester.TryEncode("foo"_span, { 0, 3, 'f', 'o' }), CHIP_ERROR_NO_MEMORY); + EXPECT_EQ(tester.TryEncode("test"_span, { 0xFF }), CHIP_ERROR_NO_MEMORY); + + EXPECT_TRUE(tester.TryEncode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + } + + { + // Insufficient space even for length + EncodeTester<1> tester(CreateFakeMeta(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_EQ(tester.TryEncode(""_span, { 0 }), CHIP_ERROR_NO_MEMORY); + } + + // bad type casts + { + EncodeTester tester(CreateFakeMeta(ZCL_CHAR_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_EQ(tester.TryEncode(ByteSpan({}), { 0 }), CHIP_ERROR_WRONG_TLV_TYPE); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT32U_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_EQ(tester.TryEncode(true, { 0 }), CHIP_ERROR_WRONG_TLV_TYPE); + } +} + +TEST(TestEmberAttributeBuffer, TestNoData) +{ + EncodeTester tester(CreateFakeMeta(ZCL_NO_DATA_ATTRIBUTE_TYPE, true /* nullable */)); + + // support a always-null type + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0 }).IsSuccess()); +} + +TEST(TestEmberAttributeBuffer, TestDecodeFailures) +{ + { + // attribute type that is not handled + EncodeTester tester(CreateFakeMeta(ZCL_UNKNOWN_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_EQ(tester.TryDecode>(DataModel::NullNullable, { 0 }), CHIP_IM_GLOBAL_STATUS(Failure)); + } + + { + // Insufficient input + EncodeTester<3> tester(CreateFakeMeta(ZCL_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_EQ(tester.TryDecode("test"_span, { 10 }), CHIP_ERROR_BUFFER_TOO_SMALL); + EXPECT_EQ(tester.TryDecode("foo"_span, { 3, 'f', 'o' }), CHIP_ERROR_BUFFER_TOO_SMALL); + } + + { + // Insufficient data buffer - should never happen, but test that we will error out + EncodeTester tester(CreateFakeMeta(ZCL_INT32U_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_EQ(tester.TryDecode(123, { 1, 2, 3 }), CHIP_ERROR_BUFFER_TOO_SMALL); + } + + { + // Insufficient data buffer - should never happen, but test that we will error out + EncodeTester tester(CreateFakeMeta(ZCL_SINGLE_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_EQ(tester.TryDecode(1.5f, { 1, 2, 3 }), CHIP_ERROR_BUFFER_TOO_SMALL); + } + + { + // Insufficient data buffer - should never happen, but test that we will error out + EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_EQ(tester.TryDecode(1.5, { 1, 2, 3 }), CHIP_ERROR_BUFFER_TOO_SMALL); + } + + { + // Bad boolean data + EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_EQ(tester.TryDecode(true, { 123 }), CHIP_ERROR_INVALID_ARGUMENT); + } +} + +TEST(TestEmberAttributeBuffer, TestDecodeSignedTypes) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8S_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(127, { 127 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-10, { 0xF6 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-128, { 0x80 }).IsSuccess()); + + // longer data is ok + EXPECT_TRUE(tester.TryDecode(-128, { 0x80, 1, 2, 3, 4 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8S_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(127, { 127 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-10, { 0xF6 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-127, { 0x81 }).IsSuccess()); + + // NULL can be decoded + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0x80 }).IsSuccess()); + + // decoding as nullable proceeds as normal + EXPECT_TRUE(tester.TryDecode>(-127, { 0x81 }).IsSuccess()); + } + + { + + EncodeTester tester(CreateFakeMeta(ZCL_INT16S_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(127, { 127, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-10, { 0xF6, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-128, { 0x80, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(std::numeric_limits::min(), { 0x0, 0x80 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT16S_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(127, { 127, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-10, { 0xF6, 0xFF }).IsSuccess()); + + // NULL decoding + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0x00, 0x80 }).IsSuccess()); + } + + // Odd size integers + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24S_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-1, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-10, { 0xF6, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24S_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-1, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-10, { 0xF6, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF }).IsSuccess()); + + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0x00, 0x00, 0x80 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT40S_ATTRIBUTE_TYPE, true /* nullable */)); + + // NOTE: to generate encoded values, you an use commands like: + // + // python -c 'import struct; print(", ".join(["0x%X" % v for v in struct.pack("(0, { 0, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x123456, { 0x56, 0x34, 0x12, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-123456789, { 0xeb, 0x32, 0xa4, 0xf8, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(-12345678910, { 0xc2, 0xe3, 0x23, 0x20, 0xfd }).IsSuccess()); + + EXPECT_TRUE( + tester.TryDecode>(DataModel::NullNullable, { 0x00, 0x00, 0x00, 0x00, 0x80 }).IsSuccess()); + } + + // Double-check tests, not as exhaustive, to cover all other unsigned values and get + // more test line coverage + { + EncodeTester tester(CreateFakeMeta(ZCL_INT32S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT48S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT56S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64S_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + + // min/max ranges too + EXPECT_TRUE( + tester.TryDecode(std::numeric_limits::min() + 1, { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }) + .IsSuccess()); + EXPECT_TRUE( + tester.TryDecode(std::numeric_limits::max(), { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }) + .IsSuccess()); + + EXPECT_TRUE(tester + .TryDecode>(DataModel::NullNullable, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }) + .IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64S_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryDecode(-1234, { 0x2E, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + + EXPECT_TRUE( + tester.TryDecode(std::numeric_limits::min(), { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }) + .IsSuccess()); + EXPECT_TRUE( + tester.TryDecode(std::numeric_limits::min() + 1, { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }) + .IsSuccess()); + EXPECT_TRUE( + tester.TryDecode(std::numeric_limits::max(), { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }) + .IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestDecodeUnsignedTypes) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8U_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xFD, { 0xFD }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(255, { 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT8U_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xFD, { 0xFD }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + + // NULL decoding should work + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT16U_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xFD, { 0xFD, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(255, { 0xFF, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xABCD, { 0xCD, 0xAB }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xFFFF, { 0xFF, 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT16U_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(123, { 123, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xFD, { 0xFD, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(255, { 0xFF, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xABCD, { 0xCD, 0xAB }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + + // NULL SUPPORT + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64U_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(0, { 0, 0, 0, 0, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x1234567, { 0x67, 0x45, 0x23, 0x01, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xAABBCCDDEEFF1122, { 0x22, 0x11, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA }).IsSuccess()); + EXPECT_TRUE( + tester.TryDecode(std::numeric_limits::max() - 1, { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }) + .IsSuccess()); + + EXPECT_TRUE(tester + .TryDecode>(DataModel::NullNullable, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }) + .IsSuccess()); + + EXPECT_TRUE(tester + .TryDecode>(DataModel::NullNullable, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }) + .IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT64U_ATTRIBUTE_TYPE, false /* nullable */)); + + // we should be able to encode the maximum value + EXPECT_TRUE( + tester.TryDecode(std::numeric_limits::max(), { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }) + .IsSuccess()); + } + + /// Odd sized integers + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24U_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryDecode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0xFFFFFF, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT24U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(0, { 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x123456, { 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF, 0xFF, 0xFF }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(0x1234, { 0x34, 0x12, 0x00 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_INT40U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(0, { 0, 0, 0, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x123456, { 0x56, 0x34, 0x12, 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(0x123456FFFF, { 0xFF, 0xFF, 0x56, 0x34, 0x12 }).IsSuccess()); + EXPECT_TRUE( + tester.TryDecode>(DataModel::NullNullable, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }).IsSuccess()); + } + + // Double-check tests, not as exhaustive, to cover all other unsigned values and get + // more test line coverage + { + EncodeTester tester(CreateFakeMeta(ZCL_INT32U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(0x1234, { 0x34, 0x12, 0, 0 }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT48U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(0x1234, { 0x34, 0x12, 0, 0, 0, 0 }).IsSuccess()); + } + { + EncodeTester tester(CreateFakeMeta(ZCL_INT56U_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(0x1234, { 0x34, 0x12, 0, 0, 0, 0, 0 }).IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestDecodeStrings) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_CHAR_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryDecode(""_span, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode("test"_span, { 4, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode("foo"_span, { 3, 'f', 'o', 'o' }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(""_span, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode("test"_span, { 4, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryDecode(""_span, { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode("test"_span, { 4, 0, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode("foo"_span, { 3, 0, 'f', 'o', 'o' }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode("test"_span, { 4, 0, 't', 'e', 's', 't' }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + } + + const uint8_t kOctetData[] = { 1, 2, 3 }; + + // Binary data + { + EncodeTester tester(CreateFakeMeta(ZCL_OCTET_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryDecode(ByteSpan({}), { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(ByteSpan(kOctetData), { 3, 1, 2, 3 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_OCTET_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(ByteSpan({}), { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(ByteSpan(kOctetData), { 3, 1, 2, 3 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryDecode(ByteSpan({}), { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(ByteSpan(kOctetData), { 3, 0, 1, 2, 3 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(ByteSpan({}), { 0, 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(ByteSpan(kOctetData), { 3, 0, 1, 2, 3 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF, 0xFF }).IsSuccess()); + } +} + +TEST(TestEmberAttributeBuffer, TestDecodeBool) +{ + { + EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, false /* nullable */)); + + EXPECT_TRUE(tester.TryDecode(true, { 1 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode(false, { 0 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, true /* nullable */)); + + EXPECT_TRUE(tester.TryDecode>(true, { 1 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(false, { 0 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0xFF }).IsSuccess()); + } + + { + // Boolean that is NOT nullable + EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_EQ(tester.TryDecode>(DataModel::NullNullable, { 0xFF }), CHIP_ERROR_INVALID_ARGUMENT); + EXPECT_EQ(tester.TryDecode(true, { 0xFF }), CHIP_ERROR_INVALID_ARGUMENT); + } +} + +TEST(TestEmberAttributeBuffer, TestDecodeFloatingPoint) +{ + // NOTE: to generate encoded values, you an use commands like: + // + // python -c 'import struct; print(", ".join(["0x%X" % v for v in struct.pack("(123.55f, { 0x9A, 0x19, 0xF7, 0x42 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_SINGLE_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(123.55f, { 0x9A, 0x19, 0xF7, 0x42 }).IsSuccess()); + EXPECT_TRUE(tester.TryDecode>(DataModel::NullNullable, { 0, 0, 0xC0, 0x7F }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_SINGLE_ATTRIBUTE_TYPE, false /* nullable */)); + // non-nullable float + EXPECT_TRUE(tester.TryDecode(std::nanf("0"), { 0, 0, 0xC0, 0x7F }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, false /* nullable */)); + EXPECT_TRUE(tester.TryDecode(123.55, { 0x33, 0x33, 0x33, 0x33, 0x33, 0xE3, 0x5E, 0x40 }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, true /* nullable */)); + EXPECT_TRUE(tester.TryDecode(123.55, { 0x33, 0x33, 0x33, 0x33, 0x33, 0xE3, 0x5E, 0x40 }).IsSuccess()); + EXPECT_TRUE( + tester.TryDecode>(123.55, { 0x33, 0x33, 0x33, 0x33, 0x33, 0xE3, 0x5E, 0x40 }).IsSuccess()); + EXPECT_TRUE( + tester.TryDecode>(DataModel::NullNullable, { 0, 0, 0, 0, 0, 0, 0xF8, 0x7F }).IsSuccess()); + } + + { + EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, false /* nullable */)); + // non-nullable double + EXPECT_TRUE(tester.TryDecode(std::nan("0"), { 0, 0, 0, 0, 0, 0, 0xF8, 0x7F }).IsSuccess()); + } +} From 3b164b3f82f7154dcd8d0f3122cc30cc17d89e38 Mon Sep 17 00:00:00 2001 From: bhmanda-silabs <107180296+bhmanda-silabs@users.noreply.github.com> Date: Sat, 15 Mar 2025 02:04:19 +0530 Subject: [PATCH 9/9] [CSA-CP] Fix the secure soc reset issue (#37965) (#344) Co-authored-by: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> --- examples/platform/silabs/Rpc.cpp | 6 ++++-- src/platform/silabs/ConfigurationManagerImpl.cpp | 2 +- src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp | 5 ++++- src/platform/silabs/platformAbstraction/GsdkSpam.cpp | 5 +++++ src/platform/silabs/platformAbstraction/SilabsPlatform.h | 2 ++ .../silabs/platformAbstraction/SilabsPlatformBase.h | 6 ++++++ src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp | 7 +++++++ 7 files changed, 29 insertions(+), 4 deletions(-) diff --git a/examples/platform/silabs/Rpc.cpp b/examples/platform/silabs/Rpc.cpp index d265e65af7..10a364cb56 100644 --- a/examples/platform/silabs/Rpc.cpp +++ b/examples/platform/silabs/Rpc.cpp @@ -21,6 +21,7 @@ #include "pigweed/RpcService.h" #include "pw_sys_io_efr32/init.h" #include +#include #include #if defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE @@ -73,6 +74,8 @@ size_t pw_trace_GetTraceTimeTicksPerSecond() #endif // defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE +using namespace chip::DeviceLayer::Silabs; + namespace chip { namespace rpc { @@ -117,7 +120,7 @@ class Efr32Device final : public Device osTimer_t mRebootTimerBuffer; osTimerAttr_t mRebootTimerAttr = { .name = "Reboot", .cb_mem = &mRebootTimerBuffer, .cb_size = osTimerCbSize }; - static void RebootHandler(void * timerCbArg) { NVIC_SystemReset(); } + static void RebootHandler(void * timerCbArg) { GetPlatform().SoftwareReset(); } }; #endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE @@ -225,6 +228,5 @@ void Init() // Start App task. sRpcTaskHandle = osThreadNew(RunRpcService, nullptr, &kRpcTaskAttr); } - } // namespace rpc } // namespace chip diff --git a/src/platform/silabs/ConfigurationManagerImpl.cpp b/src/platform/silabs/ConfigurationManagerImpl.cpp index 668b150ccc..f8be7114cb 100644 --- a/src/platform/silabs/ConfigurationManagerImpl.cpp +++ b/src/platform/silabs/ConfigurationManagerImpl.cpp @@ -306,7 +306,7 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) // Block the task for 500 ms before the reset occurs to allow RPC response to be sent vTaskDelay(pdMS_TO_TICKS(500)); - NVIC_SystemReset(); + Silabs::GetPlatform().SoftwareReset(); } #ifdef SL_WIFI diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp index 3829cb1db5..1be182a82a 100644 --- a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #if CHIP_CONFIG_ENABLE_ICD_SERVER #include @@ -42,6 +43,8 @@ extern "C" { uint8_t flag = RPS_HEADER; static chip::OTAImageProcessorImpl gImageProcessor; +using namespace chip::DeviceLayer::Silabs; + namespace chip { // Define static memebers @@ -228,7 +231,7 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) // send system reset request to reset the MCU and upgrade the m4 image ChipLogProgress(SoftwareUpdate, "SoC Soft Reset initiated!"); // Reboots the device - sl_si91x_soc_nvic_reset(); + GetPlatform().SoftwareReset(); } } diff --git a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp index bc221ead6a..7b57604a6c 100644 --- a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp +++ b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp @@ -124,6 +124,11 @@ CHIP_ERROR SilabsPlatform::Init(void) return CHIP_NO_ERROR; } +void SilabsPlatform::SoftwareReset() +{ + NVIC_SystemReset(); +} + CHIP_ERROR SilabsPlatform::FlashInit() { #if defined(SL_TRUSTZONE_NONSECURE) diff --git a/src/platform/silabs/platformAbstraction/SilabsPlatform.h b/src/platform/silabs/platformAbstraction/SilabsPlatform.h index df84224c50..fb596f103a 100644 --- a/src/platform/silabs/platformAbstraction/SilabsPlatform.h +++ b/src/platform/silabs/platformAbstraction/SilabsPlatform.h @@ -61,6 +61,8 @@ class SilabsPlatform : virtual public SilabsPlatformAbstractionBase CHIP_ERROR FlashErasePage(uint32_t addr) override; CHIP_ERROR FlashWritePage(uint32_t addr, const uint8_t * data, size_t size) override; + void SoftwareReset(void) override; + private: friend SilabsPlatform & GetPlatform(void); diff --git a/src/platform/silabs/platformAbstraction/SilabsPlatformBase.h b/src/platform/silabs/platformAbstraction/SilabsPlatformBase.h index 818463ecfb..555847c99e 100644 --- a/src/platform/silabs/platformAbstraction/SilabsPlatformBase.h +++ b/src/platform/silabs/platformAbstraction/SilabsPlatformBase.h @@ -56,6 +56,12 @@ class SilabsPlatformAbstractionBase virtual CHIP_ERROR FlashErasePage(uint32_t addr) { return CHIP_ERROR_NOT_IMPLEMENTED; } virtual CHIP_ERROR FlashWritePage(uint32_t addr, const uint8_t * data, size_t size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + /** + * @brief Function trigger the platform to execute a software reset. + * Anything after this function will not be executed since the device will reboot. + */ + virtual void SoftwareReset(void) = 0; + // BLE Specific Method protected: diff --git a/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp b/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp index 2d052a6bcd..0eb978428d 100644 --- a/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp +++ b/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp @@ -38,6 +38,8 @@ extern "C" { #endif // SL_SI91X_BOARD_INIT #include "sl_event_handler.h" +#include "sl_si91x_hal_soc_soft_reset.h" + #ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT #include "sl_si91x_button.h" #include "sl_si91x_button_pin_config.h" @@ -208,6 +210,11 @@ uint8_t SilabsPlatform::GetButtonState(uint8_t button) } #endif // SL_CATALOG_SIMPLE_BUTTON_PRESENT +void SilabsPlatform::SoftwareReset() +{ + sl_si91x_soc_nvic_reset(); +} + CHIP_ERROR SilabsPlatform::FlashInit() { return CHIP_NO_ERROR;