From 17aede590506a0ac3ffb85f0ced8465e88780022 Mon Sep 17 00:00:00 2001 From: chirag-silabs <100861685+chirag-silabs@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:03:20 +0530 Subject: [PATCH 01/33] [Silabs] Adding the spi_multiplex.h for only NCP not SOC devices (#31276) * adding the condition for only ncp devices not SOC * Restyled by clang-format --------- Co-authored-by: Restyled.io --- examples/thermostat/silabs/src/ThermostatUI.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/thermostat/silabs/src/ThermostatUI.cpp b/examples/thermostat/silabs/src/ThermostatUI.cpp index 9d84517e0fb5c3..77184151e1d1d3 100644 --- a/examples/thermostat/silabs/src/ThermostatUI.cpp +++ b/examples/thermostat/silabs/src/ThermostatUI.cpp @@ -25,7 +25,8 @@ #include "glib.h" #include "lcd.h" -#if SL_WIFI +#if SL_WIFI && !defined(SIWX_917) +// Only needed for wifi NCP devices #include "spi_multiplex.h" #endif // SL_WIFI From fdcb54b15cfb0fc032c1c4b5f7bd4683140e8ecf Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Mon, 8 Jan 2024 17:33:06 +0200 Subject: [PATCH 02/33] [Telink] Update Docker image (Zephyr update) (#31292) --- integrations/docker/images/base/chip-build/version | 2 +- integrations/docker/images/stage-2/chip-build-telink/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 106a5cfbec0cab..8b85550a4399e5 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -31 : [silabs] Update gsdk and wifi-sdk +32 : [Telink] Update Docker image (Zephyr update) diff --git a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile index 8c1662607fdccb..e67b4ef3977bea 100644 --- a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile @@ -12,7 +12,7 @@ RUN set -x \ && : # last line # Setup Zephyr -ARG ZEPHYR_REVISION=e0800ce0375563dfeea8ffc32ebc78d5aaf4f091 +ARG ZEPHYR_REVISION=d074f4f945919a37214a5f8ee608f4107c108c20 WORKDIR /opt/telink/zephyrproject RUN set -x \ && python3 -m pip install -U --no-cache-dir west \ From 72a8652dcde731e36102cb501922f6427b062c34 Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Mon, 8 Jan 2024 17:35:36 +0200 Subject: [PATCH 03/33] [Telink] Retention memory optimization (#31293) * [Telink] Move mFactoryDataBuffer out of retention memory * [Telink] Enable factory data by default for tests * [Telink] Add NFC for commissioning comment * Revert "[Telink] Enable factory data by default for tests" This reverts commit 59c87a9ceb5b1c508f37355f5aa1dd3cfa1b41b2. * Restyled by clang-format --------- Co-authored-by: Restyled.io --- examples/lighting-app/telink/prj.conf | 1 + src/platform/telink/FactoryDataProvider.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/lighting-app/telink/prj.conf b/examples/lighting-app/telink/prj.conf index 4bd1798b99e560..87a5c03720bbf4 100644 --- a/examples/lighting-app/telink/prj.conf +++ b/examples/lighting-app/telink/prj.conf @@ -42,6 +42,7 @@ CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y # Disable CHIP shell support CONFIG_CHIP_LIB_SHELL=n +# Disable CHIP NFC for commissioning CONFIG_CHIP_NFC_COMMISSIONING=n # Disable factory data support diff --git a/src/platform/telink/FactoryDataProvider.h b/src/platform/telink/FactoryDataProvider.h index 829831e554aa33..18bb8f3bea6867 100644 --- a/src/platform/telink/FactoryDataProvider.h +++ b/src/platform/telink/FactoryDataProvider.h @@ -30,6 +30,8 @@ namespace chip { namespace DeviceLayer { +__attribute__((section(".bss"))) static uint8_t mFactoryDataBuffer[FIXED_PARTITION_SIZE(factory_partition)]; + struct InternalFlashFactoryData { CHIP_ERROR GetFactoryDataPartition(uint8_t *& data, size_t & dataSize) @@ -63,7 +65,6 @@ struct ExternalFlashFactoryData CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite() { return CHIP_ERROR_NOT_IMPLEMENTED; } const struct device * mFlashDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)); - uint8_t mFactoryDataBuffer[FIXED_PARTITION_SIZE(factory_partition)]; }; template From ce79b3fd5aff4324e5e2f41ebc42ab86b095fa8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:38:28 +0000 Subject: [PATCH 04/33] Bump third_party/pigweed/repo from `355d707` to `cbbc73d` (#31283) Bumps [third_party/pigweed/repo](https://github.com/google/pigweed) from `355d707` to `cbbc73d`. - [Commits](https://github.com/google/pigweed/compare/355d7079513c7036c82e664b2bb0b5d8f4cc4e01...cbbc73dc4d56bc201e9d50c4b10db974aff82754) --- updated-dependencies: - dependency-name: third_party/pigweed/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/pigweed/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/pigweed/repo b/third_party/pigweed/repo index 355d7079513c70..cbbc73dc4d56bc 160000 --- a/third_party/pigweed/repo +++ b/third_party/pigweed/repo @@ -1 +1 @@ -Subproject commit 355d7079513c7036c82e664b2bb0b5d8f4cc4e01 +Subproject commit cbbc73dc4d56bc201e9d50c4b10db974aff82754 From 375195c9bb2f166149b1a0b0baf1b8d5e15fd28d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:38:56 +0000 Subject: [PATCH 05/33] Bump third_party/editline/repo from `7633fbc` to `4255848` (#31282) Bumps [third_party/editline/repo](https://github.com/troglobit/editline) from `7633fbc` to `4255848`. - [Release notes](https://github.com/troglobit/editline/releases) - [Commits](https://github.com/troglobit/editline/compare/7633fbceeeeb5376a1e24e0949aa9724cf4b0077...425584840c09f83bb8fedbf76b599d3a917621ba) --- updated-dependencies: - dependency-name: third_party/editline/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/editline/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/editline/repo b/third_party/editline/repo index 7633fbceeeeb53..425584840c09f8 160000 --- a/third_party/editline/repo +++ b/third_party/editline/repo @@ -1 +1 @@ -Subproject commit 7633fbceeeeb5376a1e24e0949aa9724cf4b0077 +Subproject commit 425584840c09f83bb8fedbf76b599d3a917621ba From 30f202a5a99b70910a022ffe920170d38b4707d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:39:25 +0000 Subject: [PATCH 06/33] Bump third_party/nanopb/repo from `5fd8f04` to `cf26d28` (#31281) Bumps [third_party/nanopb/repo](https://github.com/nanopb/nanopb) from `5fd8f04` to `cf26d28`. - [Commits](https://github.com/nanopb/nanopb/compare/5fd8f04a48be1a250c3bbdc9f7c782ef2c372e74...cf26d28b88010dd3ac94e0cba64d4a71522154bc) --- updated-dependencies: - dependency-name: third_party/nanopb/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/nanopb/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/nanopb/repo b/third_party/nanopb/repo index 5fd8f04a48be1a..cf26d28b88010d 160000 --- a/third_party/nanopb/repo +++ b/third_party/nanopb/repo @@ -1 +1 @@ -Subproject commit 5fd8f04a48be1a250c3bbdc9f7c782ef2c372e74 +Subproject commit cf26d28b88010dd3ac94e0cba64d4a71522154bc From 1971a5cc003865268b0a5ec8633b591cbd7d34fb Mon Sep 17 00:00:00 2001 From: Terence Hampson Date: Mon, 8 Jan 2024 12:31:55 -0500 Subject: [PATCH 07/33] New unit testing cluster commands to support testing batch commands corner cases (#31138) * New unit testing cluster commands for batch testing * Restyled by whitespace * Restyled by clang-format * Address PR comments * Restyled by clang-format * Fixes for CI * Restyled by prettier-yaml * Fix Darwin codegen for adding new commands to UnitTesting. 1) Add missing isSupported check that was causing us to generate an implementation that did not have a corresponding declaration (which had the check). 2) Add missing isForCommandPayload to existing isSupported check, so implementation and declaration are doing the same check. 3) Mark newly-added things as provisional. * Rerun zap regen --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .../all-clusters-app.matter | 22 ++ .../all-clusters-common/all-clusters-app.zap | 28 +- .../all-clusters-minimal-app.matter | 20 ++ .../test-cluster-server.cpp | 87 ++++++ src/app/tests/suites/TestCluster.yaml | 25 +- .../zcl/data-model/chip/test-cluster.xml | 27 ++ .../data_model/controller-clusters.matter | 20 ++ .../chip/devicecontroller/ChipClusters.java | 80 ++++++ .../devicecontroller/ClusterIDMapping.java | 38 ++- .../devicecontroller/ClusterInfoMapping.java | 82 ++++++ .../cluster/clusters/UnitTestingCluster.kt | 118 ++++++++ .../zap-generated/CHIPInvokeCallbacks.cpp | 60 ++++ .../java/zap-generated/CHIPInvokeCallbacks.h | 15 + .../python/chip/clusters/CHIPClusters.py | 18 ++ .../python/chip/clusters/Objects.py | 56 ++++ .../templates/MTRCommandPayloadsObjc-src.zapt | 4 +- .../CHIP/templates/availability.yaml | 6 + .../CHIP/zap-generated/MTRBaseClusters.h | 12 + .../CHIP/zap-generated/MTRBaseClusters.mm | 48 ++++ .../CHIP/zap-generated/MTRClusterConstants.h | 3 + .../CHIP/zap-generated/MTRClusters.h | 2 + .../CHIP/zap-generated/MTRClusters.mm | 54 ++++ .../zap-generated/MTRCommandPayloadsObjc.h | 87 ++++++ .../zap-generated/MTRCommandPayloadsObjc.mm | 261 ++++++++++++++++++ .../MTRCommandPayloads_Internal.h | 18 ++ .../app-common/zap-generated/callback.h | 12 + .../zap-generated/cluster-objects.cpp | 122 ++++++++ .../zap-generated/cluster-objects.h | 123 +++++++++ .../app-common/zap-generated/ids/Commands.h | 12 + .../zap-generated/cluster/Commands.h | 84 ++++++ .../cluster/logging/DataModelLogger.cpp | 13 + .../cluster/logging/DataModelLogger.h | 2 + .../zap-generated/cluster/Commands.h | 151 ++++++++++ .../zap-generated/test/Commands.h | 7 +- 34 files changed, 1705 insertions(+), 12 deletions(-) diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index c09d305dd7390b..b17ab915e55a98 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -6198,6 +6198,10 @@ internal cluster UnitTesting = 4294048773 { NestedStructList arg1[] = 0; } + response struct TestBatchHelperResponse = 12 { + octet_string<800> buffer = 0; + } + request struct TestListInt8UReverseRequestRequest { int8u arg1[] = 0; } @@ -6244,6 +6248,18 @@ internal cluster UnitTesting = 4294048773 { int8u arg1 = 0; } + request struct TestBatchHelperRequestRequest { + int16u sleepBeforeResponseTimeMs = 0; + int16u sizeOfResponseBuffer = 1; + int8u fillCharacter = 2; + } + + request struct TestSecondBatchHelperRequestRequest { + int16u sleepBeforeResponseTimeMs = 0; + int16u sizeOfResponseBuffer = 1; + int8u fillCharacter = 2; + } + /** Simple command without any parameters and without a specific response */ command Test(): DefaultSuccess = 0; /** Simple command without any parameters and without a specific response not handled by the server */ @@ -6309,6 +6325,10 @@ internal cluster UnitTesting = 4294048773 { command TestEmitTestEventRequest(TestEmitTestEventRequestRequest): TestEmitTestEventResponse = 20; /** Command that takes identical arguments to the fields of the TestFabricScopedEvent and logs the TestFabricScopedEvent to the buffer. Command returns an event ID as the response. */ command TestEmitTestFabricScopedEventRequest(TestEmitTestFabricScopedEventRequestRequest): TestEmitTestFabricScopedEventResponse = 21; + /** Command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. */ + command TestBatchHelperRequest(TestBatchHelperRequestRequest): TestBatchHelperResponse = 22; + /** Second command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. */ + command TestSecondBatchHelperRequest(TestSecondBatchHelperRequestRequest): TestBatchHelperResponse = 23; } /** The Fault Injection Cluster provide a means for a test harness to configure faults(for example triggering a fault in the system). */ @@ -8012,6 +8032,8 @@ endpoint 1 { handle command TestSimpleOptionalArgumentRequest; handle command TestEmitTestEventRequest; handle command TestEmitTestFabricScopedEventRequest; + handle command TestBatchHelperRequest; + handle command TestSecondBatchHelperRequest; } } endpoint 2 { diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 8f1d73386c7465..a5d06276bbc56e 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -17,6 +17,12 @@ } ], "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" + }, { "pathRelativity": "relativeToZap", "path": "../../../src/app/zap-templates/zcl/zcl-with-test-extensions.json", @@ -24,12 +30,6 @@ "category": "matter", "version": 1, "description": "Matter SDK ZCL data with some extensions" - }, - { - "pathRelativity": "relativeToZap", - "path": "../../../src/app/zap-templates/app-templates.json", - "type": "gen-templates-json", - "version": "chip-v1" } ], "endpointTypes": [ @@ -19318,6 +19318,22 @@ "source": "client", "isIncoming": 1, "isEnabled": 1 + }, + { + "name": "TestBatchHelperRequest", + "code": 22, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TestSecondBatchHelperRequest", + "code": 23, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 } ], "attributes": [ diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter index 42daa8ddac3aa8..601b3e82450bd2 100644 --- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter +++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter @@ -5601,6 +5601,10 @@ internal cluster UnitTesting = 4294048773 { NestedStructList arg1[] = 0; } + response struct TestBatchHelperResponse = 12 { + octet_string<800> buffer = 0; + } + request struct TestListInt8UReverseRequestRequest { int8u arg1[] = 0; } @@ -5647,6 +5651,18 @@ internal cluster UnitTesting = 4294048773 { int8u arg1 = 0; } + request struct TestBatchHelperRequestRequest { + int16u sleepBeforeResponseTimeMs = 0; + int16u sizeOfResponseBuffer = 1; + int8u fillCharacter = 2; + } + + request struct TestSecondBatchHelperRequestRequest { + int16u sleepBeforeResponseTimeMs = 0; + int16u sizeOfResponseBuffer = 1; + int8u fillCharacter = 2; + } + /** Simple command without any parameters and without a specific response */ command Test(): DefaultSuccess = 0; /** Simple command without any parameters and without a specific response not handled by the server */ @@ -5712,6 +5728,10 @@ internal cluster UnitTesting = 4294048773 { command TestEmitTestEventRequest(TestEmitTestEventRequestRequest): TestEmitTestEventResponse = 20; /** Command that takes identical arguments to the fields of the TestFabricScopedEvent and logs the TestFabricScopedEvent to the buffer. Command returns an event ID as the response. */ command TestEmitTestFabricScopedEventRequest(TestEmitTestFabricScopedEventRequestRequest): TestEmitTestFabricScopedEventResponse = 21; + /** Command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. */ + command TestBatchHelperRequest(TestBatchHelperRequestRequest): TestBatchHelperResponse = 22; + /** Second command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. */ + command TestSecondBatchHelperRequest(TestSecondBatchHelperRequestRequest): TestBatchHelperResponse = 23; } endpoint 0 { diff --git a/src/app/clusters/test-cluster-server/test-cluster-server.cpp b/src/app/clusters/test-cluster-server/test-cluster-server.cpp index 30d1fb4a6edaa1..de41c286f15f2d 100644 --- a/src/app/clusters/test-cluster-server/test-cluster-server.cpp +++ b/src/app/clusters/test-cluster-server/test-cluster-server.cpp @@ -55,6 +55,9 @@ constexpr uint8_t kFabricSensitiveCharLength = 128; // The maximum length of the fabric sensitive integer list within the TestFabricScoped struct. constexpr uint8_t kFabricSensitiveIntListLength = 8; +// The maximum buffer size allowed in TestBatchHelperResponse +constexpr uint16_t kTestBatchHelperResponseBufferMax = 800; + namespace { class OctetStringData @@ -103,6 +106,14 @@ class TestAttrAccess : public AttributeAccessInterface CHIP_ERROR WriteListFabricScopedAttribute(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder); }; +struct AsyncBatchCommandsWorkData +{ + CommandHandler::Handle asyncCommandHandle; + ConcreteCommandPath commandPath = ConcreteCommandPath(0, 0, 0); + uint16_t sizeOfResponseBuffer; + uint8_t fillCharacter; +}; + TestAttrAccess gAttrAccess; uint8_t gListUint8Data[kAttributeListLength]; size_t gListUint8DataLen = kAttributeListLength; @@ -137,6 +148,36 @@ SimpleEnum gSimpleEnums[kAttributeListLength]; size_t gSimpleEnumCount = 0; Structs::NullablesAndOptionalsStruct::Type gNullablesAndOptionalsStruct; +void AsyncBatchCommandWork(AsyncBatchCommandsWorkData * asyncWorkData) +{ + auto commandHandleRef = std::move(asyncWorkData->asyncCommandHandle); + auto commandHandle = commandHandleRef.Get(); + if (commandHandle == nullptr) + { + // Very weird that we are even in here, what set this to nullptr? + Platform::Delete(asyncWorkData); + return; + } + + uint8_t buffer[kTestBatchHelperResponseBufferMax]; + memset(buffer, asyncWorkData->fillCharacter, asyncWorkData->sizeOfResponseBuffer); + Commands::TestBatchHelperResponse::Type response; + response.buffer = ByteSpan(buffer, asyncWorkData->sizeOfResponseBuffer); + commandHandle->AddResponse(asyncWorkData->commandPath, response); + Platform::Delete(asyncWorkData); +} + +static void timerCallback(System::Layer *, void * callbackContext) +{ + AsyncBatchCommandWork(reinterpret_cast(callbackContext)); +} + +static void scheduleTimerCallbackMs(AsyncBatchCommandsWorkData * asyncWorkData, uint32_t delayMs) +{ + DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(delayMs), timerCallback, + reinterpret_cast(asyncWorkData)); +} + CHIP_ERROR TestAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) { switch (aPath.mAttributeId) @@ -994,6 +1035,52 @@ bool emberAfUnitTestingClusterTestSimpleOptionalArgumentRequestCallback( return true; } +// TestBatchHelperRequest and TestSecondBatchHelperRequest do the same thing. +// The reason there are two identical commands is because batch command requires +// command paths in the same batch to be unique. These command allow for +// client to control order of the response and control size of CommandDataIB +// being sent back to help test some corner cases. +bool TestBatchHelperCommon(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const uint16_t sleepTimeMs, + const uint16_t sizeOfResponseBuffer, const uint8_t fillCharacter) +{ + if (sizeOfResponseBuffer > kTestBatchHelperResponseBufferMax) + { + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::ConstraintError); + return true; + } + + AsyncBatchCommandsWorkData * asyncWorkData = Platform::New(); + if (asyncWorkData == nullptr) + { + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Busy); + return true; + } + + asyncWorkData->asyncCommandHandle = commandObj; + asyncWorkData->commandPath = commandPath; + asyncWorkData->sizeOfResponseBuffer = sizeOfResponseBuffer; + asyncWorkData->fillCharacter = fillCharacter; + + scheduleTimerCallbackMs(asyncWorkData, sleepTimeMs); + + return true; +} + +bool emberAfUnitTestingClusterTestBatchHelperRequestCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, + const Commands::TestBatchHelperRequest::DecodableType & commandData) +{ + return TestBatchHelperCommon(commandObj, commandPath, commandData.sleepBeforeResponseTimeMs, commandData.sizeOfResponseBuffer, + commandData.fillCharacter); +} + +bool emberAfUnitTestingClusterTestSecondBatchHelperRequestCallback( + CommandHandler * commandObj, const ConcreteCommandPath & commandPath, + const Commands::TestSecondBatchHelperRequest::DecodableType & commandData) +{ + return TestBatchHelperCommon(commandObj, commandPath, commandData.sleepBeforeResponseTimeMs, commandData.sizeOfResponseBuffer, + commandData.fillCharacter); +} + // ----------------------------------------------------------------------------- // Plugin initialization diff --git a/src/app/tests/suites/TestCluster.yaml b/src/app/tests/suites/TestCluster.yaml index e89a892dd32ee5..c6e8dc0946970c 100644 --- a/src/app/tests/suites/TestCluster.yaml +++ b/src/app/tests/suites/TestCluster.yaml @@ -3855,13 +3855,34 @@ tests: attribute: "AcceptedCommandList" response: value: - [0, 1, 2, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21] + [ + 0, + 1, + 2, + 4, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + ] - label: "read GeneratedCommandList attribute" command: "readAttribute" attribute: "GeneratedCommandList" response: - value: [0, 1, 4, 5, 6, 8, 9, 10, 11] + value: [0, 1, 4, 5, 6, 8, 9, 10, 11, 12] # Struct-typed attribute - label: "Write struct-typed attribute" diff --git a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml index 6e81b67b5c46e9..f043c49074ec0e 100644 --- a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml @@ -440,6 +440,26 @@ limitations under the License. + + + Command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. + + + + + + + + + Second command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. + + + + + + Simple response for TestWithResponse with a simple return value @@ -566,6 +586,13 @@ limitations under the License. + + + Response to TestBatchHelperRequest or TestSecondBatchHelperRequest. Buffer in response is filled as directed in the Request. + + + + Example test event diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 380270d146601a..70cef4b39d5675 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -8693,6 +8693,10 @@ internal cluster UnitTesting = 4294048773 { NestedStructList arg1[] = 0; } + response struct TestBatchHelperResponse = 12 { + octet_string<800> buffer = 0; + } + request struct TestListInt8UReverseRequestRequest { int8u arg1[] = 0; } @@ -8739,6 +8743,18 @@ internal cluster UnitTesting = 4294048773 { int8u arg1 = 0; } + request struct TestBatchHelperRequestRequest { + int16u sleepBeforeResponseTimeMs = 0; + int16u sizeOfResponseBuffer = 1; + int8u fillCharacter = 2; + } + + request struct TestSecondBatchHelperRequestRequest { + int16u sleepBeforeResponseTimeMs = 0; + int16u sizeOfResponseBuffer = 1; + int8u fillCharacter = 2; + } + /** Simple command without any parameters and without a specific response */ command Test(): DefaultSuccess = 0; /** Simple command without any parameters and without a specific response not handled by the server */ @@ -8804,6 +8820,10 @@ internal cluster UnitTesting = 4294048773 { command TestEmitTestEventRequest(TestEmitTestEventRequestRequest): TestEmitTestEventResponse = 20; /** Command that takes identical arguments to the fields of the TestFabricScopedEvent and logs the TestFabricScopedEvent to the buffer. Command returns an event ID as the response. */ command TestEmitTestFabricScopedEventRequest(TestEmitTestFabricScopedEventRequestRequest): TestEmitTestFabricScopedEventResponse = 21; + /** Command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. */ + command TestBatchHelperRequest(TestBatchHelperRequestRequest): TestBatchHelperResponse = 22; + /** Second command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. */ + command TestSecondBatchHelperRequest(TestSecondBatchHelperRequestRequest): TestBatchHelperResponse = 23; } /** The Fault Injection Cluster provide a means for a test harness to configure faults(for example triggering a fault in the system). */ diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index d9b1143464b577..eb221bfec1730b 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -58464,6 +58464,82 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, value, timedInvokeTimeoutMs); } + public void testBatchHelperRequest(TestBatchHelperResponseCallback callback, Integer sleepBeforeResponseTimeMs, Integer sizeOfResponseBuffer, Integer fillCharacter) { + testBatchHelperRequest(callback, sleepBeforeResponseTimeMs, sizeOfResponseBuffer, fillCharacter, 0); + } + + public void testBatchHelperRequest(TestBatchHelperResponseCallback callback, Integer sleepBeforeResponseTimeMs, Integer sizeOfResponseBuffer, Integer fillCharacter, int timedInvokeTimeoutMs) { + final long commandId = 22L; + + ArrayList elements = new ArrayList<>(); + final long sleepBeforeResponseTimeMsFieldID = 0L; + BaseTLVType sleepBeforeResponseTimeMstlvValue = new UIntType(sleepBeforeResponseTimeMs); + elements.add(new StructElement(sleepBeforeResponseTimeMsFieldID, sleepBeforeResponseTimeMstlvValue)); + + final long sizeOfResponseBufferFieldID = 1L; + BaseTLVType sizeOfResponseBuffertlvValue = new UIntType(sizeOfResponseBuffer); + elements.add(new StructElement(sizeOfResponseBufferFieldID, sizeOfResponseBuffertlvValue)); + + final long fillCharacterFieldID = 2L; + BaseTLVType fillCharactertlvValue = new UIntType(fillCharacter); + elements.add(new StructElement(fillCharacterFieldID, fillCharactertlvValue)); + + StructType value = new StructType(elements); + invoke(new InvokeCallbackImpl(callback) { + @Override + public void onResponse(StructType invokeStructValue) { + final long bufferFieldID = 0L; + byte[] buffer = null; + for (StructElement element: invokeStructValue.value()) { + if (element.contextTagNum() == bufferFieldID) { + if (element.value(BaseTLVType.class).type() == TLVType.ByteArray) { + ByteArrayType castingValue = element.value(ByteArrayType.class); + buffer = castingValue.value(byte[].class); + } + } + } + callback.onSuccess(buffer); + }}, commandId, value, timedInvokeTimeoutMs); + } + + public void testSecondBatchHelperRequest(TestBatchHelperResponseCallback callback, Integer sleepBeforeResponseTimeMs, Integer sizeOfResponseBuffer, Integer fillCharacter) { + testSecondBatchHelperRequest(callback, sleepBeforeResponseTimeMs, sizeOfResponseBuffer, fillCharacter, 0); + } + + public void testSecondBatchHelperRequest(TestBatchHelperResponseCallback callback, Integer sleepBeforeResponseTimeMs, Integer sizeOfResponseBuffer, Integer fillCharacter, int timedInvokeTimeoutMs) { + final long commandId = 23L; + + ArrayList elements = new ArrayList<>(); + final long sleepBeforeResponseTimeMsFieldID = 0L; + BaseTLVType sleepBeforeResponseTimeMstlvValue = new UIntType(sleepBeforeResponseTimeMs); + elements.add(new StructElement(sleepBeforeResponseTimeMsFieldID, sleepBeforeResponseTimeMstlvValue)); + + final long sizeOfResponseBufferFieldID = 1L; + BaseTLVType sizeOfResponseBuffertlvValue = new UIntType(sizeOfResponseBuffer); + elements.add(new StructElement(sizeOfResponseBufferFieldID, sizeOfResponseBuffertlvValue)); + + final long fillCharacterFieldID = 2L; + BaseTLVType fillCharactertlvValue = new UIntType(fillCharacter); + elements.add(new StructElement(fillCharacterFieldID, fillCharactertlvValue)); + + StructType value = new StructType(elements); + invoke(new InvokeCallbackImpl(callback) { + @Override + public void onResponse(StructType invokeStructValue) { + final long bufferFieldID = 0L; + byte[] buffer = null; + for (StructElement element: invokeStructValue.value()) { + if (element.contextTagNum() == bufferFieldID) { + if (element.value(BaseTLVType.class).type() == TLVType.ByteArray) { + ByteArrayType castingValue = element.value(ByteArrayType.class); + buffer = castingValue.value(byte[].class); + } + } + } + callback.onSuccess(buffer); + }}, commandId, value, timedInvokeTimeoutMs); + } + public interface TestSpecificResponseCallback extends BaseClusterCallback { void onSuccess(Integer returnValue); } @@ -58512,6 +58588,10 @@ public interface TestEmitTestFabricScopedEventResponseCallback extends BaseClust void onSuccess(Long value); } + public interface TestBatchHelperResponseCallback extends BaseClusterCallback { + void onSuccess(byte[] buffer); + } + public interface ListInt8uAttributeCallback extends BaseAttributeCallback { void onSuccess(List value); } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index e432edea9dc9c3..77021a240507ed 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -16053,7 +16053,9 @@ public enum Command { TimedInvokeRequest(18L), TestSimpleOptionalArgumentRequest(19L), TestEmitTestEventRequest(20L), - TestEmitTestFabricScopedEventRequest(21L),; + TestEmitTestFabricScopedEventRequest(21L), + TestBatchHelperRequest(22L), + TestSecondBatchHelperRequest(23L),; private final long id; Command(long id) { this.id = id; @@ -16360,6 +16362,40 @@ public static TestEmitTestFabricScopedEventRequestCommandField value(int id) thr } throw new NoSuchFieldError(); } + }public enum TestBatchHelperRequestCommandField {SleepBeforeResponseTimeMs(0),SizeOfResponseBuffer(1),FillCharacter(2),; + private final int id; + TestBatchHelperRequestCommandField(int id) { + this.id = id; + } + + public int getID() { + return id; + } + public static TestBatchHelperRequestCommandField value(int id) throws NoSuchFieldError { + for (TestBatchHelperRequestCommandField field : TestBatchHelperRequestCommandField.values()) { + if (field.getID() == id) { + return field; + } + } + throw new NoSuchFieldError(); + } + }public enum TestSecondBatchHelperRequestCommandField {SleepBeforeResponseTimeMs(0),SizeOfResponseBuffer(1),FillCharacter(2),; + private final int id; + TestSecondBatchHelperRequestCommandField(int id) { + this.id = id; + } + + public int getID() { + return id; + } + public static TestSecondBatchHelperRequestCommandField value(int id) throws NoSuchFieldError { + for (TestSecondBatchHelperRequestCommandField field : TestSecondBatchHelperRequestCommandField.values()) { + if (field.getID() == id) { + return field; + } + } + throw new NoSuchFieldError(); + } }@Override public String getAttributeName(long id) throws NoSuchFieldError { return Attribute.value(id).toString(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index 187400cba467b4..a0a05852bd9c69 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -18312,6 +18312,28 @@ public void onError(Exception error) { callback.onFailure(error); } } + + public static class DelegatedUnitTestingClusterTestBatchHelperResponseCallback implements ChipClusters.UnitTestingCluster.TestBatchHelperResponseCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(byte[] buffer) { + Map responseValues = new LinkedHashMap<>(); + + CommandResponseInfo bufferResponseValue = new CommandResponseInfo("buffer", "byte[]"); + responseValues.put(bufferResponseValue, buffer); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception error) { + callback.onFailure(error); + } + } public static class DelegatedUnitTestingClusterListInt8uAttributeCallback implements ChipClusters.UnitTestingCluster.ListInt8uAttributeCallback, DelegatedClusterCallback { private ClusterCommandCallback callback; @Override @@ -26190,6 +26212,66 @@ public Map> getCommandMap() { ); unitTestingClusterInteractionInfoMap.put("testEmitTestFabricScopedEventRequest", unitTestingtestEmitTestFabricScopedEventRequestInteractionInfo); + Map unitTestingtestBatchHelperRequestCommandParams = new LinkedHashMap(); + + CommandParameterInfo unitTestingtestBatchHelperRequestsleepBeforeResponseTimeMsCommandParameterInfo = new CommandParameterInfo("sleepBeforeResponseTimeMs", Integer.class, Integer.class); + unitTestingtestBatchHelperRequestCommandParams.put("sleepBeforeResponseTimeMs",unitTestingtestBatchHelperRequestsleepBeforeResponseTimeMsCommandParameterInfo); + + CommandParameterInfo unitTestingtestBatchHelperRequestsizeOfResponseBufferCommandParameterInfo = new CommandParameterInfo("sizeOfResponseBuffer", Integer.class, Integer.class); + unitTestingtestBatchHelperRequestCommandParams.put("sizeOfResponseBuffer",unitTestingtestBatchHelperRequestsizeOfResponseBufferCommandParameterInfo); + + CommandParameterInfo unitTestingtestBatchHelperRequestfillCharacterCommandParameterInfo = new CommandParameterInfo("fillCharacter", Integer.class, Integer.class); + unitTestingtestBatchHelperRequestCommandParams.put("fillCharacter",unitTestingtestBatchHelperRequestfillCharacterCommandParameterInfo); + InteractionInfo unitTestingtestBatchHelperRequestInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.UnitTestingCluster) cluster) + .testBatchHelperRequest((ChipClusters.UnitTestingCluster.TestBatchHelperResponseCallback) callback + , (Integer) + commandArguments.get("sleepBeforeResponseTimeMs") + + , (Integer) + commandArguments.get("sizeOfResponseBuffer") + + , (Integer) + commandArguments.get("fillCharacter") + + ); + }, + () -> new DelegatedUnitTestingClusterTestBatchHelperResponseCallback(), + unitTestingtestBatchHelperRequestCommandParams + ); + unitTestingClusterInteractionInfoMap.put("testBatchHelperRequest", unitTestingtestBatchHelperRequestInteractionInfo); + + Map unitTestingtestSecondBatchHelperRequestCommandParams = new LinkedHashMap(); + + CommandParameterInfo unitTestingtestSecondBatchHelperRequestsleepBeforeResponseTimeMsCommandParameterInfo = new CommandParameterInfo("sleepBeforeResponseTimeMs", Integer.class, Integer.class); + unitTestingtestSecondBatchHelperRequestCommandParams.put("sleepBeforeResponseTimeMs",unitTestingtestSecondBatchHelperRequestsleepBeforeResponseTimeMsCommandParameterInfo); + + CommandParameterInfo unitTestingtestSecondBatchHelperRequestsizeOfResponseBufferCommandParameterInfo = new CommandParameterInfo("sizeOfResponseBuffer", Integer.class, Integer.class); + unitTestingtestSecondBatchHelperRequestCommandParams.put("sizeOfResponseBuffer",unitTestingtestSecondBatchHelperRequestsizeOfResponseBufferCommandParameterInfo); + + CommandParameterInfo unitTestingtestSecondBatchHelperRequestfillCharacterCommandParameterInfo = new CommandParameterInfo("fillCharacter", Integer.class, Integer.class); + unitTestingtestSecondBatchHelperRequestCommandParams.put("fillCharacter",unitTestingtestSecondBatchHelperRequestfillCharacterCommandParameterInfo); + InteractionInfo unitTestingtestSecondBatchHelperRequestInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.UnitTestingCluster) cluster) + .testSecondBatchHelperRequest((ChipClusters.UnitTestingCluster.TestBatchHelperResponseCallback) callback + , (Integer) + commandArguments.get("sleepBeforeResponseTimeMs") + + , (Integer) + commandArguments.get("sizeOfResponseBuffer") + + , (Integer) + commandArguments.get("fillCharacter") + + ); + }, + () -> new DelegatedUnitTestingClusterTestBatchHelperResponseCallback(), + unitTestingtestSecondBatchHelperRequestCommandParams + ); + unitTestingClusterInteractionInfoMap.put("testSecondBatchHelperRequest", unitTestingtestSecondBatchHelperRequestInteractionInfo); + commandMap.put("unitTesting", unitTestingClusterInteractionInfoMap); Map faultInjectionClusterInteractionInfoMap = new LinkedHashMap<>(); diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/UnitTestingCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/UnitTestingCluster.kt index 94fe39115cd7a2..468d4e4b310802 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/UnitTestingCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/UnitTestingCluster.kt @@ -119,6 +119,8 @@ class UnitTestingCluster(private val controller: MatterController, private val e class TestEmitTestFabricScopedEventResponse(val value: ULong) + class TestBatchHelperResponse(val buffer: ByteArray) + class ListInt8uAttribute(val value: List) sealed class ListInt8uAttributeSubscriptionState { @@ -2217,6 +2219,122 @@ class UnitTestingCluster(private val controller: MatterController, private val e return TestEmitTestFabricScopedEventResponse(value_decoded) } + suspend fun testBatchHelperRequest( + sleepBeforeResponseTimeMs: UShort, + sizeOfResponseBuffer: UShort, + fillCharacter: UByte, + timedInvokeTimeout: Duration? = null + ): TestBatchHelperResponse { + val commandId: UInt = 22u + + val tlvWriter = TlvWriter() + tlvWriter.startStructure(AnonymousTag) + + val TAG_SLEEP_BEFORE_RESPONSE_TIME_MS_REQ: Int = 0 + tlvWriter.put( + ContextSpecificTag(TAG_SLEEP_BEFORE_RESPONSE_TIME_MS_REQ), + sleepBeforeResponseTimeMs + ) + + val TAG_SIZE_OF_RESPONSE_BUFFER_REQ: Int = 1 + tlvWriter.put(ContextSpecificTag(TAG_SIZE_OF_RESPONSE_BUFFER_REQ), sizeOfResponseBuffer) + + val TAG_FILL_CHARACTER_REQ: Int = 2 + tlvWriter.put(ContextSpecificTag(TAG_FILL_CHARACTER_REQ), fillCharacter) + tlvWriter.endStructure() + + val request: InvokeRequest = + InvokeRequest( + CommandPath(endpointId, clusterId = CLUSTER_ID, commandId), + tlvPayload = tlvWriter.getEncoded(), + timedRequest = timedInvokeTimeout + ) + + val response: InvokeResponse = controller.invoke(request) + logger.log(Level.FINE, "Invoke command succeeded: ${response}") + + val tlvReader = TlvReader(response.payload) + tlvReader.enterStructure(AnonymousTag) + val TAG_BUFFER: Int = 0 + var buffer_decoded: ByteArray? = null + + while (!tlvReader.isEndOfContainer()) { + val tag = tlvReader.peekElement().tag + + if (tag == ContextSpecificTag(TAG_BUFFER)) { + buffer_decoded = tlvReader.getByteArray(tag) + } else { + tlvReader.skipElement() + } + } + + if (buffer_decoded == null) { + throw IllegalStateException("buffer not found in TLV") + } + + tlvReader.exitContainer() + + return TestBatchHelperResponse(buffer_decoded) + } + + suspend fun testSecondBatchHelperRequest( + sleepBeforeResponseTimeMs: UShort, + sizeOfResponseBuffer: UShort, + fillCharacter: UByte, + timedInvokeTimeout: Duration? = null + ): TestBatchHelperResponse { + val commandId: UInt = 23u + + val tlvWriter = TlvWriter() + tlvWriter.startStructure(AnonymousTag) + + val TAG_SLEEP_BEFORE_RESPONSE_TIME_MS_REQ: Int = 0 + tlvWriter.put( + ContextSpecificTag(TAG_SLEEP_BEFORE_RESPONSE_TIME_MS_REQ), + sleepBeforeResponseTimeMs + ) + + val TAG_SIZE_OF_RESPONSE_BUFFER_REQ: Int = 1 + tlvWriter.put(ContextSpecificTag(TAG_SIZE_OF_RESPONSE_BUFFER_REQ), sizeOfResponseBuffer) + + val TAG_FILL_CHARACTER_REQ: Int = 2 + tlvWriter.put(ContextSpecificTag(TAG_FILL_CHARACTER_REQ), fillCharacter) + tlvWriter.endStructure() + + val request: InvokeRequest = + InvokeRequest( + CommandPath(endpointId, clusterId = CLUSTER_ID, commandId), + tlvPayload = tlvWriter.getEncoded(), + timedRequest = timedInvokeTimeout + ) + + val response: InvokeResponse = controller.invoke(request) + logger.log(Level.FINE, "Invoke command succeeded: ${response}") + + val tlvReader = TlvReader(response.payload) + tlvReader.enterStructure(AnonymousTag) + val TAG_BUFFER: Int = 0 + var buffer_decoded: ByteArray? = null + + while (!tlvReader.isEndOfContainer()) { + val tag = tlvReader.peekElement().tag + + if (tag == ContextSpecificTag(TAG_BUFFER)) { + buffer_decoded = tlvReader.getByteArray(tag) + } else { + tlvReader.skipElement() + } + } + + if (buffer_decoded == null) { + throw IllegalStateException("buffer not found in TLV") + } + + tlvReader.exitContainer() + + return TestBatchHelperResponse(buffer_decoded) + } + suspend fun readBooleanAttribute(): Boolean { val ATTRIBUTE_ID: UInt = 0u diff --git a/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp b/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp index c8b5c50edc55e8..8c3deacae5abaf 100644 --- a/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp +++ b/src/controller/java/zap-generated/CHIPInvokeCallbacks.cpp @@ -8330,6 +8330,66 @@ void CHIPUnitTestingClusterTestEmitTestFabricScopedEventResponseCallback::Callba env->CallVoidMethod(javaCallbackRef, javaMethod, value); } +CHIPUnitTestingClusterTestBatchHelperResponseCallback::CHIPUnitTestingClusterTestBatchHelperResponseCallback(jobject javaCallback) : + Callback::Callback(CallbackFn, this) +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + if (env == nullptr) + { + ChipLogError(Zcl, "Could not create global reference for Java callback"); + return; + } + + javaCallbackRef = env->NewGlobalRef(javaCallback); + if (javaCallbackRef == nullptr) + { + ChipLogError(Zcl, "Could not create global reference for Java callback"); + } +} + +CHIPUnitTestingClusterTestBatchHelperResponseCallback::~CHIPUnitTestingClusterTestBatchHelperResponseCallback() +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + if (env == nullptr) + { + ChipLogError(Zcl, "Could not delete global reference for Java callback"); + return; + } + env->DeleteGlobalRef(javaCallbackRef); +}; + +void CHIPUnitTestingClusterTestBatchHelperResponseCallback::CallbackFn( + void * context, const chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType & dataResponse) +{ + chip::DeviceLayer::StackUnlock unlock; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + jobject javaCallbackRef; + jmethodID javaMethod; + + VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Error invoking Java callback: no JNIEnv")); + + std::unique_ptr + cppCallback(reinterpret_cast(context), + chip::Platform::Delete); + VerifyOrReturn(cppCallback != nullptr, ChipLogError(Zcl, "Error invoking Java callback: failed to cast native callback")); + + javaCallbackRef = cppCallback->javaCallbackRef; + // Java callback is allowed to be null, exit early if this is the case. + VerifyOrReturn(javaCallbackRef != nullptr); + + err = JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "([B)V", &javaMethod); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error invoking Java callback: %s", ErrorStr(err))); + + jobject buffer; + jbyteArray bufferByteArray = env->NewByteArray(static_cast(dataResponse.buffer.size())); + env->SetByteArrayRegion(bufferByteArray, 0, static_cast(dataResponse.buffer.size()), + reinterpret_cast(dataResponse.buffer.data())); + buffer = bufferByteArray; + + env->CallVoidMethod(javaCallbackRef, javaMethod, buffer); +} CHIPSampleMeiClusterAddArgumentsResponseCallback::CHIPSampleMeiClusterAddArgumentsResponseCallback(jobject javaCallback) : Callback::Callback(CallbackFn, this) { diff --git a/src/controller/java/zap-generated/CHIPInvokeCallbacks.h b/src/controller/java/zap-generated/CHIPInvokeCallbacks.h index 23b691e07a332b..1a0c0dd4d2ef50 100644 --- a/src/controller/java/zap-generated/CHIPInvokeCallbacks.h +++ b/src/controller/java/zap-generated/CHIPInvokeCallbacks.h @@ -1126,6 +1126,21 @@ class CHIPUnitTestingClusterTestEmitTestFabricScopedEventResponseCallback jobject javaCallbackRef; }; +class CHIPUnitTestingClusterTestBatchHelperResponseCallback + : public Callback::Callback +{ +public: + CHIPUnitTestingClusterTestBatchHelperResponseCallback(jobject javaCallback); + + ~CHIPUnitTestingClusterTestBatchHelperResponseCallback(); + + static void CallbackFn(void * context, + const chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType & data); + +private: + jobject javaCallbackRef; +}; + class CHIPSampleMeiClusterAddArgumentsResponseCallback : public Callback::Callback { diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 57d6c97e833340..59c67cbe244eb2 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -13126,6 +13126,24 @@ class ChipClusters: "arg1": "int", }, }, + 0x00000016: { + "commandId": 0x00000016, + "commandName": "TestBatchHelperRequest", + "args": { + "sleepBeforeResponseTimeMs": "int", + "sizeOfResponseBuffer": "int", + "fillCharacter": "int", + }, + }, + 0x00000017: { + "commandId": 0x00000017, + "commandName": "TestSecondBatchHelperRequest", + "args": { + "sleepBeforeResponseTimeMs": "int", + "sizeOfResponseBuffer": "int", + "fillCharacter": "int", + }, + }, }, "attributes": { 0x00000000: { diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index c5874b2aaec964..ac7aeca1cab875 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -45541,6 +45541,22 @@ def descriptor(cls) -> ClusterObjectDescriptor: arg1: 'typing.List[UnitTesting.Structs.NestedStructList]' = field(default_factory=lambda: []) + @dataclass + class TestBatchHelperResponse(ClusterCommand): + cluster_id: typing.ClassVar[int] = 0xFFF1FC05 + command_id: typing.ClassVar[int] = 0x0000000C + is_client: typing.ClassVar[bool] = False + response_type: typing.ClassVar[str] = None + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="buffer", Tag=0, Type=bytes), + ]) + + buffer: 'bytes' = b"" + @dataclass class TestListInt8UReverseRequest(ClusterCommand): cluster_id: typing.ClassVar[int] = 0xFFF1FC05 @@ -45714,6 +45730,46 @@ def descriptor(cls) -> ClusterObjectDescriptor: arg1: 'uint' = 0 + @dataclass + class TestBatchHelperRequest(ClusterCommand): + cluster_id: typing.ClassVar[int] = 0xFFF1FC05 + command_id: typing.ClassVar[int] = 0x00000016 + is_client: typing.ClassVar[bool] = True + response_type: typing.ClassVar[str] = 'TestBatchHelperResponse' + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="sleepBeforeResponseTimeMs", Tag=0, Type=uint), + ClusterObjectFieldDescriptor(Label="sizeOfResponseBuffer", Tag=1, Type=uint), + ClusterObjectFieldDescriptor(Label="fillCharacter", Tag=2, Type=uint), + ]) + + sleepBeforeResponseTimeMs: 'uint' = 0 + sizeOfResponseBuffer: 'uint' = 0 + fillCharacter: 'uint' = 0 + + @dataclass + class TestSecondBatchHelperRequest(ClusterCommand): + cluster_id: typing.ClassVar[int] = 0xFFF1FC05 + command_id: typing.ClassVar[int] = 0x00000017 + is_client: typing.ClassVar[bool] = True + response_type: typing.ClassVar[str] = 'TestBatchHelperResponse' + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="sleepBeforeResponseTimeMs", Tag=0, Type=uint), + ClusterObjectFieldDescriptor(Label="sizeOfResponseBuffer", Tag=1, Type=uint), + ClusterObjectFieldDescriptor(Label="fillCharacter", Tag=2, Type=uint), + ]) + + sleepBeforeResponseTimeMs: 'uint' = 0 + sizeOfResponseBuffer: 'uint' = 0 + fillCharacter: 'uint' = 0 + class Attributes: @dataclass class Boolean(ClusterAttributeDescriptor): diff --git a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt index aa7fe84de732d2..c58c75f77d9d38 100644 --- a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt @@ -198,6 +198,7 @@ NS_ASSUME_NONNULL_BEGIN {{/if}} {{/inline}} {{#*inline "oldNameImpl"}} +{{#if (isSupported cluster command=command isForCommandPayload=true)}} @implementation MTR{{cluster}}Cluster{{command}}Params {{#zcl_command_arguments}} @@ -213,8 +214,9 @@ NS_ASSUME_NONNULL_BEGIN @dynamic timedInvokeTimeoutMs; {{/if}} @end +{{/if}} {{/inline}} -{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}} +{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true) isForCommandPayload=true)}} {{> completeImpl cluster=(asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true) includeRenamedProperties=false}} diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index 0911dd0118fe3e..ae0d02274db63b 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -8313,6 +8313,12 @@ - ActivateAudioTrack - ActivateTextTrack - DeactivateTextTrack + UnitTesting: + # Ideally none of UnitTesting would be exposed as public API, but + # for now just start doing that for new additions to it. + - TestBatchHelperResponse + - TestBatchHelperRequest + - TestSecondBatchHelperRequest command fields: NetworkCommissioning: # Targeting Spring 2024 Matter release diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index ffa6767035e2b3..1ae4424f2229fb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -14764,6 +14764,18 @@ MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) * Command that takes identical arguments to the fields of the TestFabricScopedEvent and logs the TestFabricScopedEvent to the buffer. Command returns an event ID as the response. */ - (void)testEmitTestFabricScopedEventRequestWithParams:(MTRUnitTestingClusterTestEmitTestFabricScopedEventRequestParams *)params completion:(void (^)(MTRUnitTestingClusterTestEmitTestFabricScopedEventResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); +/** + * Command TestBatchHelperRequest + * + * Command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. + */ +- (void)testBatchHelperRequestWithParams:(MTRUnitTestingClusterTestBatchHelperRequestParams *)params completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +/** + * Command TestSecondBatchHelperRequest + * + * Second command that responds after sleepBeforeResponseTimeMs with an octet_string the size requested with fillCharacter. + */ +- (void)testSecondBatchHelperRequestWithParams:(MTRUnitTestingClusterTestSecondBatchHelperRequestParams *)params completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)readAttributeBooleanWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); - (void)writeAttributeBooleanWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index 19b00a2c799aaa..1050bcbbc044ca 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -109665,6 +109665,54 @@ - (void)testEmitTestFabricScopedEventRequestWithParams:(MTRUnitTestingClusterTes queue:self.callbackQueue completion:responseHandler]; } +- (void)testBatchHelperRequestWithParams:(MTRUnitTestingClusterTestBatchHelperRequestParams *)params completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion +{ + if (params == nil) { + params = [[MTRUnitTestingClusterTestBatchHelperRequestParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(response, error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = UnitTesting::Commands::TestBatchHelperRequest::Type; + [self.device _invokeKnownCommandWithEndpointID:@(self.endpoint) + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:MTRUnitTestingClusterTestBatchHelperResponseParams.class + queue:self.callbackQueue + completion:responseHandler]; +} +- (void)testSecondBatchHelperRequestWithParams:(MTRUnitTestingClusterTestSecondBatchHelperRequestParams *)params completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion +{ + if (params == nil) { + params = [[MTRUnitTestingClusterTestSecondBatchHelperRequestParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(response, error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = UnitTesting::Commands::TestSecondBatchHelperRequest::Type; + [self.device _invokeKnownCommandWithEndpointID:@(self.endpoint) + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:MTRUnitTestingClusterTestBatchHelperResponseParams.class + queue:self.callbackQueue + completion:responseHandler]; +} - (void)readAttributeBooleanWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 8e618740b0b6da..4cf0aa3990a7dd 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -6918,6 +6918,7 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterUnitTestingCommandTestNestedStructListArgumentRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x0000000B, MTRCommandIDTypeClusterUnitTestingCommandTestEmitTestFabricScopedEventResponseID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x0000000B, MTRCommandIDTypeClusterUnitTestingCommandTestListNestedStructListArgumentRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x0000000C, + MTRCommandIDTypeClusterUnitTestingCommandTestBatchHelperResponseID MTR_PROVISIONALLY_AVAILABLE = 0x0000000C, MTRCommandIDTypeClusterUnitTestingCommandTestListInt8UReverseRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x0000000D, MTRCommandIDTypeClusterUnitTestingCommandTestEnumsRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x0000000E, MTRCommandIDTypeClusterUnitTestingCommandTestNullableOptionalRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x0000000F, @@ -6927,6 +6928,8 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterUnitTestingCommandTestSimpleOptionalArgumentRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000013, MTRCommandIDTypeClusterUnitTestingCommandTestEmitTestEventRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000014, MTRCommandIDTypeClusterUnitTestingCommandTestEmitTestFabricScopedEventRequestID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000015, + MTRCommandIDTypeClusterUnitTestingCommandTestBatchHelperRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000016, + MTRCommandIDTypeClusterUnitTestingCommandTestSecondBatchHelperRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000017, // Cluster SampleMEI commands MTRCommandIDTypeClusterSampleMEICommandPingID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index 7e3c9eb87cf9c7..b377db1108216e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -6730,6 +6730,8 @@ MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)); - (void)testEmitTestEventRequestWithParams:(MTRUnitTestingClusterTestEmitTestEventRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRUnitTestingClusterTestEmitTestEventResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); - (void)testEmitTestFabricScopedEventRequestWithParams:(MTRUnitTestingClusterTestEmitTestFabricScopedEventRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRUnitTestingClusterTestEmitTestFabricScopedEventResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); +- (void)testBatchHelperRequestWithParams:(MTRUnitTestingClusterTestBatchHelperRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)testSecondBatchHelperRequestWithParams:(MTRUnitTestingClusterTestSecondBatchHelperRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeBooleanWithParams:(MTRReadParams * _Nullable)params MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); - (void)writeAttributeBooleanWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index 0ab55d5776856e..f8bb88a0ef0152 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -19977,6 +19977,60 @@ - (void)testEmitTestFabricScopedEventRequestWithParams:(MTRUnitTestingClusterTes completion:responseHandler]; } +- (void)testBatchHelperRequestWithParams:(MTRUnitTestingClusterTestBatchHelperRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion +{ + if (params == nil) { + params = [[MTRUnitTestingClusterTestBatchHelperRequestParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(response, error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = UnitTesting::Commands::TestBatchHelperRequest::Type; + [self.device _invokeKnownCommandWithEndpointID:@(self.endpoint) + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + expectedValues:expectedValues + expectedValueInterval:expectedValueIntervalMs + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:MTRUnitTestingClusterTestBatchHelperResponseParams.class + queue:self.callbackQueue + completion:responseHandler]; +} + +- (void)testSecondBatchHelperRequestWithParams:(MTRUnitTestingClusterTestSecondBatchHelperRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable data, NSError * _Nullable error))completion +{ + if (params == nil) { + params = [[MTRUnitTestingClusterTestSecondBatchHelperRequestParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(response, error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = UnitTesting::Commands::TestSecondBatchHelperRequest::Type; + [self.device _invokeKnownCommandWithEndpointID:@(self.endpoint) + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + expectedValues:expectedValues + expectedValueInterval:expectedValueIntervalMs + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:MTRUnitTestingClusterTestBatchHelperResponseParams.class + queue:self.callbackQueue + completion:responseHandler]; +} + - (NSDictionary * _Nullable)readAttributeBooleanWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:@(self.endpoint) clusterID:@(MTRClusterIDTypeUnitTestingID) attributeID:@(MTRAttributeIDTypeClusterUnitTestingAttributeBooleanID) params:params]; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index f540aa11163f6d..a3177639b26409 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -11959,6 +11959,25 @@ MTR_DEPRECATED("Please use MTRUnitTestingClusterTestListNestedStructListArgument @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end +MTR_PROVISIONALLY_AVAILABLE +@interface MTRUnitTestingClusterTestBatchHelperResponseParams : NSObject + +@property (nonatomic, copy) NSData * _Nonnull buffer MTR_PROVISIONALLY_AVAILABLE; + +/** + * Initialize an MTRUnitTestingClusterTestBatchHelperResponseParams with a response-value dictionary + * of the sort that MTRDeviceResponseHandler would receive. + * + * Will return nil and hand out an error if the response-value dictionary is not + * a command data response or is not the right command response. + * + * Will return nil and hand out an error if the data response does not match the known + * schema for this command. + */ +- (nullable instancetype)initWithResponseValue:(NSDictionary *)responseValue + error:(NSError * __autoreleasing *)error MTR_PROVISIONALLY_AVAILABLE; +@end + MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) @interface MTRUnitTestingClusterTestListInt8UReverseRequestParams : NSObject @@ -12551,6 +12570,74 @@ MTR_DEPRECATED("Please use MTRUnitTestingClusterTestEmitTestFabricScopedEventReq @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end +MTR_PROVISIONALLY_AVAILABLE +@interface MTRUnitTestingClusterTestBatchHelperRequestParams : NSObject + +@property (nonatomic, copy) NSNumber * _Nonnull sleepBeforeResponseTimeMs MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull sizeOfResponseBuffer MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull fillCharacter MTR_PROVISIONALLY_AVAILABLE; +/** + * Controls whether the command is a timed command (using Timed Invoke). + * + * If nil (the default value), a regular invoke is done for commands that do + * not require a timed invoke and a timed invoke with some default timed request + * timeout is done for commands that require a timed invoke. + * + * If not nil, a timed invoke is done, with the provided value used as the timed + * request timeout. The value should be chosen small enough to provide the + * desired security properties but large enough that it will allow a round-trip + * from the sever to the client (for the status response and actual invoke + * request) within the timeout window. + * + */ +@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; + +/** + * Controls how much time, in seconds, we will allow for the server to process the command. + * + * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. + * + * If nil, the framework will try to select an appropriate timeout value itself. + */ +@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; +@end + +MTR_PROVISIONALLY_AVAILABLE +@interface MTRUnitTestingClusterTestSecondBatchHelperRequestParams : NSObject + +@property (nonatomic, copy) NSNumber * _Nonnull sleepBeforeResponseTimeMs MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull sizeOfResponseBuffer MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull fillCharacter MTR_PROVISIONALLY_AVAILABLE; +/** + * Controls whether the command is a timed command (using Timed Invoke). + * + * If nil (the default value), a regular invoke is done for commands that do + * not require a timed invoke and a timed invoke with some default timed request + * timeout is done for commands that require a timed invoke. + * + * If not nil, a timed invoke is done, with the provided value used as the timed + * request timeout. The value should be chosen small enough to provide the + * desired security properties but large enough that it will allow a round-trip + * from the sever to the client (for the status response and actual invoke + * request) within the timeout window. + * + */ +@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; + +/** + * Controls how much time, in seconds, we will allow for the server to process the command. + * + * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. + * + * If nil, the framework will try to select an appropriate timeout value itself. + */ +@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; +@end + MTR_PROVISIONALLY_AVAILABLE @interface MTRSampleMEIClusterPingParams : NSObject /** diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index 35c71e8afd4c3f..368ac07c4a2ac3 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -32513,6 +32513,85 @@ @implementation MTRTestClusterClusterTestListNestedStructListArgumentRequestPara @dynamic timedInvokeTimeoutMs; @dynamic serverSideProcessingTimeout; @end +@implementation MTRUnitTestingClusterTestBatchHelperResponseParams +- (instancetype)init +{ + if (self = [super init]) { + + _buffer = [NSData data]; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone; +{ + auto other = [[MTRUnitTestingClusterTestBatchHelperResponseParams alloc] init]; + + other.buffer = self.buffer; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: buffer:%@; >", NSStringFromClass([self class]), [_buffer base64EncodedStringWithOptions:0]]; + return descriptionString; +} + +- (nullable instancetype)initWithResponseValue:(NSDictionary *)responseValue + error:(NSError * __autoreleasing *)error +{ + if (!(self = [super init])) { + return nil; + } + + using DecodableType = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType; + chip::System::PacketBufferHandle buffer = [MTRBaseDevice _responseDataForCommand:responseValue + clusterID:DecodableType::GetClusterId() + commandID:DecodableType::GetCommandId() + error:error]; + if (buffer.IsNull()) { + return nil; + } + + chip::TLV::TLVReader reader; + reader.Init(buffer->Start(), buffer->DataLength()); + + CHIP_ERROR err = reader.Next(chip::TLV::AnonymousTag()); + if (err == CHIP_NO_ERROR) { + DecodableType decodedStruct; + err = chip::app::DataModel::Decode(reader, decodedStruct); + if (err == CHIP_NO_ERROR) { + err = [self _setFieldsFromDecodableStruct:decodedStruct]; + if (err == CHIP_NO_ERROR) { + return self; + } + } + } + + NSString * errorStr = [NSString stringWithFormat:@"Command payload decoding failed: %s", err.AsString()]; + MTR_LOG_ERROR("%s", errorStr.UTF8String); + if (error != nil) { + NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : NSLocalizedString(errorStr, nil) }; + *error = [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeSchemaMismatch userInfo:userInfo]; + } + return nil; +} + +@end + +@implementation MTRUnitTestingClusterTestBatchHelperResponseParams (InternalMethods) + +- (CHIP_ERROR)_setFieldsFromDecodableStruct:(const chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType &)decodableStruct +{ + { + self.buffer = AsData(decodableStruct.buffer); + } + return CHIP_NO_ERROR; +} + +@end + @implementation MTRUnitTestingClusterTestListInt8UReverseRequestParams - (instancetype)init { @@ -33556,6 +33635,188 @@ @implementation MTRTestClusterClusterTestEmitTestFabricScopedEventRequestParams @dynamic timedInvokeTimeoutMs; @dynamic serverSideProcessingTimeout; @end +@implementation MTRUnitTestingClusterTestBatchHelperRequestParams +- (instancetype)init +{ + if (self = [super init]) { + + _sleepBeforeResponseTimeMs = @(0); + + _sizeOfResponseBuffer = @(0); + + _fillCharacter = @(0); + _timedInvokeTimeoutMs = nil; + _serverSideProcessingTimeout = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone; +{ + auto other = [[MTRUnitTestingClusterTestBatchHelperRequestParams alloc] init]; + + other.sleepBeforeResponseTimeMs = self.sleepBeforeResponseTimeMs; + other.sizeOfResponseBuffer = self.sizeOfResponseBuffer; + other.fillCharacter = self.fillCharacter; + other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; + other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: sleepBeforeResponseTimeMs:%@; sizeOfResponseBuffer:%@; fillCharacter:%@; >", NSStringFromClass([self class]), _sleepBeforeResponseTimeMs, _sizeOfResponseBuffer, _fillCharacter]; + return descriptionString; +} + +@end + +@implementation MTRUnitTestingClusterTestBatchHelperRequestParams (InternalMethods) + +- (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader +{ + chip::app::Clusters::UnitTesting::Commands::TestBatchHelperRequest::Type encodableStruct; + ListFreer listFreer; + { + encodableStruct.sleepBeforeResponseTimeMs = self.sleepBeforeResponseTimeMs.unsignedShortValue; + } + { + encodableStruct.sizeOfResponseBuffer = self.sizeOfResponseBuffer.unsignedShortValue; + } + { + encodableStruct.fillCharacter = self.fillCharacter.unsignedCharValue; + } + + auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); + if (buffer.IsNull()) { + return CHIP_ERROR_NO_MEMORY; + } + + chip::System::PacketBufferTLVWriter writer; + // Commands never need chained buffers, since they cannot be chunked. + writer.Init(std::move(buffer), /* useChainedBuffers = */ false); + + ReturnErrorOnFailure(chip::app::DataModel::Encode(writer, chip::TLV::AnonymousTag(), encodableStruct)); + + ReturnErrorOnFailure(writer.Finalize(&buffer)); + + reader.Init(std::move(buffer)); + return reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()); +} + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error +{ + chip::System::PacketBufferTLVReader reader; + CHIP_ERROR err = [self _encodeToTLVReader:reader]; + if (err != CHIP_NO_ERROR) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:err]; + } + return nil; + } + + auto decodedObj = MTRDecodeDataValueDictionaryFromCHIPTLV(&reader); + if (decodedObj == nil) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; + } + } + return decodedObj; +} +@end + +@implementation MTRUnitTestingClusterTestSecondBatchHelperRequestParams +- (instancetype)init +{ + if (self = [super init]) { + + _sleepBeforeResponseTimeMs = @(0); + + _sizeOfResponseBuffer = @(0); + + _fillCharacter = @(0); + _timedInvokeTimeoutMs = nil; + _serverSideProcessingTimeout = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone; +{ + auto other = [[MTRUnitTestingClusterTestSecondBatchHelperRequestParams alloc] init]; + + other.sleepBeforeResponseTimeMs = self.sleepBeforeResponseTimeMs; + other.sizeOfResponseBuffer = self.sizeOfResponseBuffer; + other.fillCharacter = self.fillCharacter; + other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; + other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: sleepBeforeResponseTimeMs:%@; sizeOfResponseBuffer:%@; fillCharacter:%@; >", NSStringFromClass([self class]), _sleepBeforeResponseTimeMs, _sizeOfResponseBuffer, _fillCharacter]; + return descriptionString; +} + +@end + +@implementation MTRUnitTestingClusterTestSecondBatchHelperRequestParams (InternalMethods) + +- (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader +{ + chip::app::Clusters::UnitTesting::Commands::TestSecondBatchHelperRequest::Type encodableStruct; + ListFreer listFreer; + { + encodableStruct.sleepBeforeResponseTimeMs = self.sleepBeforeResponseTimeMs.unsignedShortValue; + } + { + encodableStruct.sizeOfResponseBuffer = self.sizeOfResponseBuffer.unsignedShortValue; + } + { + encodableStruct.fillCharacter = self.fillCharacter.unsignedCharValue; + } + + auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); + if (buffer.IsNull()) { + return CHIP_ERROR_NO_MEMORY; + } + + chip::System::PacketBufferTLVWriter writer; + // Commands never need chained buffers, since they cannot be chunked. + writer.Init(std::move(buffer), /* useChainedBuffers = */ false); + + ReturnErrorOnFailure(chip::app::DataModel::Encode(writer, chip::TLV::AnonymousTag(), encodableStruct)); + + ReturnErrorOnFailure(writer.Finalize(&buffer)); + + reader.Init(std::move(buffer)); + return reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()); +} + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error +{ + chip::System::PacketBufferTLVReader reader; + CHIP_ERROR err = [self _encodeToTLVReader:reader]; + if (err != CHIP_NO_ERROR) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:err]; + } + return nil; + } + + auto decodedObj = MTRDecodeDataValueDictionaryFromCHIPTLV(&reader); + if (decodedObj == nil) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; + } + } + return decodedObj; +} +@end + @implementation MTRSampleMEIClusterPingParams - (instancetype)init { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h index 24ef38c1031cc6..eaf1bf2b744f8c 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h @@ -2014,6 +2014,12 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface MTRUnitTestingClusterTestBatchHelperResponseParams (InternalMethods) + +- (CHIP_ERROR)_setFieldsFromDecodableStruct:(const chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType &)decodableStruct; + +@end + @interface MTRUnitTestingClusterTestListInt8UReverseRequestParams (InternalMethods) - (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; @@ -2068,6 +2074,18 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface MTRUnitTestingClusterTestBatchHelperRequestParams (InternalMethods) + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; + +@end + +@interface MTRUnitTestingClusterTestSecondBatchHelperRequestParams (InternalMethods) + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; + +@end + @interface MTRSampleMEIClusterPingParams (InternalMethods) - (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index 439ed6b63ab082..61c909519685e1 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -10980,6 +10980,18 @@ bool emberAfUnitTestingClusterTestEmitTestEventRequestCallback( bool emberAfUnitTestingClusterTestEmitTestFabricScopedEventRequestCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::UnitTesting::Commands::TestEmitTestFabricScopedEventRequest::DecodableType & commandData); +/** + * @brief Unit Testing Cluster TestBatchHelperRequest Command callback (from client) + */ +bool emberAfUnitTestingClusterTestBatchHelperRequestCallback( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::UnitTesting::Commands::TestBatchHelperRequest::DecodableType & commandData); +/** + * @brief Unit Testing Cluster TestSecondBatchHelperRequest Command callback (from client) + */ +bool emberAfUnitTestingClusterTestSecondBatchHelperRequestCallback( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::UnitTesting::Commands::TestSecondBatchHelperRequest::DecodableType & commandData); /** * @brief Fault Injection Cluster FailAtFault Command callback (from client) */ diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index 7d25bcce933bb4..e3798e4613005c 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -27154,6 +27154,40 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } } } // namespace TestListNestedStructListArgumentRequest. +namespace TestBatchHelperResponse { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kBuffer), buffer); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kBuffer)) + { + err = DataModel::Decode(reader, buffer); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} +} // namespace TestBatchHelperResponse. namespace TestListInt8UReverseRequest { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { @@ -27516,6 +27550,94 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } } } // namespace TestEmitTestFabricScopedEventRequest. +namespace TestBatchHelperRequest { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kSleepBeforeResponseTimeMs), sleepBeforeResponseTimeMs); + encoder.Encode(to_underlying(Fields::kSizeOfResponseBuffer), sizeOfResponseBuffer); + encoder.Encode(to_underlying(Fields::kFillCharacter), fillCharacter); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kSleepBeforeResponseTimeMs)) + { + err = DataModel::Decode(reader, sleepBeforeResponseTimeMs); + } + else if (__context_tag == to_underlying(Fields::kSizeOfResponseBuffer)) + { + err = DataModel::Decode(reader, sizeOfResponseBuffer); + } + else if (__context_tag == to_underlying(Fields::kFillCharacter)) + { + err = DataModel::Decode(reader, fillCharacter); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} +} // namespace TestBatchHelperRequest. +namespace TestSecondBatchHelperRequest { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kSleepBeforeResponseTimeMs), sleepBeforeResponseTimeMs); + encoder.Encode(to_underlying(Fields::kSizeOfResponseBuffer), sizeOfResponseBuffer); + encoder.Encode(to_underlying(Fields::kFillCharacter), fillCharacter); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kSleepBeforeResponseTimeMs)) + { + err = DataModel::Decode(reader, sleepBeforeResponseTimeMs); + } + else if (__context_tag == to_underlying(Fields::kSizeOfResponseBuffer)) + { + err = DataModel::Decode(reader, sizeOfResponseBuffer); + } + else if (__context_tag == to_underlying(Fields::kFillCharacter)) + { + err = DataModel::Decode(reader, fillCharacter); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} +} // namespace TestSecondBatchHelperRequest. } // namespace Commands namespace Attributes { diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index c292a11f999cd8..cb176c39ba7394 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -39687,6 +39687,11 @@ struct Type; struct DecodableType; } // namespace TestListNestedStructListArgumentRequest +namespace TestBatchHelperResponse { +struct Type; +struct DecodableType; +} // namespace TestBatchHelperResponse + namespace TestListInt8UReverseRequest { struct Type; struct DecodableType; @@ -39732,6 +39737,16 @@ struct Type; struct DecodableType; } // namespace TestEmitTestFabricScopedEventRequest +namespace TestBatchHelperRequest { +struct Type; +struct DecodableType; +} // namespace TestBatchHelperRequest + +namespace TestSecondBatchHelperRequest { +struct Type; +struct DecodableType; +} // namespace TestSecondBatchHelperRequest + } // namespace Commands namespace Commands { @@ -40645,6 +40660,38 @@ struct DecodableType CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace TestListNestedStructListArgumentRequest +namespace TestBatchHelperResponse { +enum class Fields : uint8_t +{ + kBuffer = 0, +}; + +struct Type +{ +public: + // Use GetCommandId instead of commandId directly to avoid naming conflict with CommandIdentification in ExecutionOfACommand + static constexpr CommandId GetCommandId() { return Commands::TestBatchHelperResponse::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::UnitTesting::Id; } + + chip::ByteSpan buffer; + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; + + using ResponseType = DataModel::NullObjectType; + + static constexpr bool MustUseTimedInvoke() { return false; } +}; + +struct DecodableType +{ +public: + static constexpr CommandId GetCommandId() { return Commands::TestBatchHelperResponse::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::UnitTesting::Id; } + + chip::ByteSpan buffer; + CHIP_ERROR Decode(TLV::TLVReader & reader); +}; +}; // namespace TestBatchHelperResponse namespace TestListInt8UReverseRequest { enum class Fields : uint8_t { @@ -40971,6 +41018,82 @@ struct DecodableType CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace TestEmitTestFabricScopedEventRequest +namespace TestBatchHelperRequest { +enum class Fields : uint8_t +{ + kSleepBeforeResponseTimeMs = 0, + kSizeOfResponseBuffer = 1, + kFillCharacter = 2, +}; + +struct Type +{ +public: + // Use GetCommandId instead of commandId directly to avoid naming conflict with CommandIdentification in ExecutionOfACommand + static constexpr CommandId GetCommandId() { return Commands::TestBatchHelperRequest::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::UnitTesting::Id; } + + uint16_t sleepBeforeResponseTimeMs = static_cast(0); + uint16_t sizeOfResponseBuffer = static_cast(0); + uint8_t fillCharacter = static_cast(0); + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; + + using ResponseType = Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType; + + static constexpr bool MustUseTimedInvoke() { return false; } +}; + +struct DecodableType +{ +public: + static constexpr CommandId GetCommandId() { return Commands::TestBatchHelperRequest::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::UnitTesting::Id; } + + uint16_t sleepBeforeResponseTimeMs = static_cast(0); + uint16_t sizeOfResponseBuffer = static_cast(0); + uint8_t fillCharacter = static_cast(0); + CHIP_ERROR Decode(TLV::TLVReader & reader); +}; +}; // namespace TestBatchHelperRequest +namespace TestSecondBatchHelperRequest { +enum class Fields : uint8_t +{ + kSleepBeforeResponseTimeMs = 0, + kSizeOfResponseBuffer = 1, + kFillCharacter = 2, +}; + +struct Type +{ +public: + // Use GetCommandId instead of commandId directly to avoid naming conflict with CommandIdentification in ExecutionOfACommand + static constexpr CommandId GetCommandId() { return Commands::TestSecondBatchHelperRequest::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::UnitTesting::Id; } + + uint16_t sleepBeforeResponseTimeMs = static_cast(0); + uint16_t sizeOfResponseBuffer = static_cast(0); + uint8_t fillCharacter = static_cast(0); + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; + + using ResponseType = Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType; + + static constexpr bool MustUseTimedInvoke() { return false; } +}; + +struct DecodableType +{ +public: + static constexpr CommandId GetCommandId() { return Commands::TestSecondBatchHelperRequest::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::UnitTesting::Id; } + + uint16_t sleepBeforeResponseTimeMs = static_cast(0); + uint16_t sizeOfResponseBuffer = static_cast(0); + uint8_t fillCharacter = static_cast(0); + CHIP_ERROR Decode(TLV::TLVReader & reader); +}; +}; // namespace TestSecondBatchHelperRequest } // namespace Commands namespace Attributes { diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h index d903540c90f79f..e5d62e248f7cdc 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h @@ -1740,6 +1740,10 @@ namespace TestListNestedStructListArgumentRequest { static constexpr CommandId Id = 0x0000000C; } // namespace TestListNestedStructListArgumentRequest +namespace TestBatchHelperResponse { +static constexpr CommandId Id = 0x0000000C; +} // namespace TestBatchHelperResponse + namespace TestListInt8UReverseRequest { static constexpr CommandId Id = 0x0000000D; } // namespace TestListInt8UReverseRequest @@ -1776,6 +1780,14 @@ namespace TestEmitTestFabricScopedEventRequest { static constexpr CommandId Id = 0x00000015; } // namespace TestEmitTestFabricScopedEventRequest +namespace TestBatchHelperRequest { +static constexpr CommandId Id = 0x00000016; +} // namespace TestBatchHelperRequest + +namespace TestSecondBatchHelperRequest { +static constexpr CommandId Id = 0x00000017; +} // namespace TestSecondBatchHelperRequest + } // namespace Commands } // namespace UnitTesting diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 1c9302b99b360c..24be99ebdc010a 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -12795,6 +12795,8 @@ class ElectricalMeasurementGetMeasurementProfileCommand : public ClusterCommand | * TestSimpleOptionalArgumentRequest | 0x13 | | * TestEmitTestEventRequest | 0x14 | | * TestEmitTestFabricScopedEventRequest | 0x15 | +| * TestBatchHelperRequest | 0x16 | +| * TestSecondBatchHelperRequest | 0x17 | |------------------------------------------------------------------------------| | Attributes: | | | * Boolean | 0x0000 | @@ -13775,6 +13777,86 @@ class UnitTestingTestEmitTestFabricScopedEventRequest : public ClusterCommand chip::app::Clusters::UnitTesting::Commands::TestEmitTestFabricScopedEventRequest::Type mRequest; }; +/* + * Command TestBatchHelperRequest + */ +class UnitTestingTestBatchHelperRequest : public ClusterCommand +{ +public: + UnitTestingTestBatchHelperRequest(CredentialIssuerCommands * credsIssuerConfig) : + ClusterCommand("test-batch-helper-request", credsIssuerConfig) + { + AddArgument("SleepBeforeResponseTimeMs", 0, UINT16_MAX, &mRequest.sleepBeforeResponseTimeMs); + AddArgument("SizeOfResponseBuffer", 0, UINT16_MAX, &mRequest.sizeOfResponseBuffer); + AddArgument("FillCharacter", 0, UINT8_MAX, &mRequest.fillCharacter); + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::UnitTesting::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, + commandId, endpointIds.at(0)); + return ClusterCommand::SendCommand(device, endpointIds.at(0), clusterId, commandId, mRequest); + } + + CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::UnitTesting::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on Group %u", clusterId, commandId, + groupId); + + return ClusterCommand::SendGroupCommand(groupId, fabricIndex, clusterId, commandId, mRequest); + } + +private: + chip::app::Clusters::UnitTesting::Commands::TestBatchHelperRequest::Type mRequest; +}; + +/* + * Command TestSecondBatchHelperRequest + */ +class UnitTestingTestSecondBatchHelperRequest : public ClusterCommand +{ +public: + UnitTestingTestSecondBatchHelperRequest(CredentialIssuerCommands * credsIssuerConfig) : + ClusterCommand("test-second-batch-helper-request", credsIssuerConfig) + { + AddArgument("SleepBeforeResponseTimeMs", 0, UINT16_MAX, &mRequest.sleepBeforeResponseTimeMs); + AddArgument("SizeOfResponseBuffer", 0, UINT16_MAX, &mRequest.sizeOfResponseBuffer); + AddArgument("FillCharacter", 0, UINT8_MAX, &mRequest.fillCharacter); + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::UnitTesting::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::UnitTesting::Commands::TestSecondBatchHelperRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, + commandId, endpointIds.at(0)); + return ClusterCommand::SendCommand(device, endpointIds.at(0), clusterId, commandId, mRequest); + } + + CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::UnitTesting::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::UnitTesting::Commands::TestSecondBatchHelperRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on Group %u", clusterId, commandId, + groupId); + + return ClusterCommand::SendGroupCommand(groupId, fabricIndex, clusterId, commandId, mRequest); + } + +private: + chip::app::Clusters::UnitTesting::Commands::TestSecondBatchHelperRequest::Type mRequest; +}; + /*----------------------------------------------------------------------------*\ | Cluster FaultInjection | 0xFFF1FC06 | |------------------------------------------------------------------------------| @@ -24899,6 +24981,8 @@ void registerClusterUnitTesting(Commands & commands, CredentialIssuerCommands * make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // + make_unique(credsIssuerConfig), // + make_unique(credsIssuerConfig), // // // Attributes // diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index 6089c40e02e3fd..8f0584c156f190 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -7302,6 +7302,14 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, DataModelLogger::LogString(indent, "}"); return CHIP_NO_ERROR; } +CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, + const UnitTesting::Commands::TestBatchHelperResponse::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + ReturnErrorOnFailure(DataModelLogger::LogValue("buffer", indent + 1, value.buffer)); + DataModelLogger::LogString(indent, "}"); + return CHIP_NO_ERROR; +} CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const SampleMei::Commands::AddArgumentsResponse::DecodableType & value) { @@ -17455,6 +17463,11 @@ CHIP_ERROR DataModelLogger::LogCommand(const chip::app::ConcreteCommandPath & pa ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("TestEmitTestFabricScopedEventResponse", 1, value); } + case UnitTesting::Commands::TestBatchHelperResponse::Id: { + UnitTesting::Commands::TestBatchHelperResponse::DecodableType value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("TestBatchHelperResponse", 1, value); + } } break; } diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h index 8828a11491c5d3..007d791c07066b 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h @@ -737,5 +737,7 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::UnitTesting::Commands::TestEmitTestFabricScopedEventResponse::DecodableType & value); +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::DecodableType & value); static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::SampleMei::Commands::AddArgumentsResponse::DecodableType & value); diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 61c9dc61e9bd56..bdfa874c995304 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -160860,6 +160860,8 @@ class SubscribeAttributeElectricalMeasurementClusterRevision : public SubscribeA | * TestSimpleOptionalArgumentRequest | 0x13 | | * TestEmitTestEventRequest | 0x14 | | * TestEmitTestFabricScopedEventRequest | 0x15 | +| * TestBatchHelperRequest | 0x16 | +| * TestSecondBatchHelperRequest | 0x17 | |------------------------------------------------------------------------------| | Attributes: | | | * Boolean | 0x0000 | @@ -162549,6 +162551,149 @@ class UnitTestingTestEmitTestFabricScopedEventRequest : public ClusterCommand { chip::app::Clusters::UnitTesting::Commands::TestEmitTestFabricScopedEventRequest::Type mRequest; }; +#if MTR_ENABLE_PROVISIONAL +/* + * Command TestBatchHelperRequest + */ +class UnitTestingTestBatchHelperRequest : public ClusterCommand { +public: + UnitTestingTestBatchHelperRequest() + : ClusterCommand("test-batch-helper-request") + { +#if MTR_ENABLE_PROVISIONAL + AddArgument("SleepBeforeResponseTimeMs", 0, UINT16_MAX, &mRequest.sleepBeforeResponseTimeMs); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("SizeOfResponseBuffer", 0, UINT16_MAX, &mRequest.sizeOfResponseBuffer); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("FillCharacter", 0, UINT8_MAX, &mRequest.fillCharacter); +#endif // MTR_ENABLE_PROVISIONAL + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::UnitTesting::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, commandId, endpointId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRUnitTestingClusterTestBatchHelperRequestParams alloc] init]; + params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; +#if MTR_ENABLE_PROVISIONAL + params.sleepBeforeResponseTimeMs = [NSNumber numberWithUnsignedShort:mRequest.sleepBeforeResponseTimeMs]; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.sizeOfResponseBuffer = [NSNumber numberWithUnsignedShort:mRequest.sizeOfResponseBuffer]; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.fillCharacter = [NSNumber numberWithUnsignedChar:mRequest.fillCharacter]; +#endif // MTR_ENABLE_PROVISIONAL + uint16_t repeatCount = mRepeatCount.ValueOr(1); + uint16_t __block responsesNeeded = repeatCount; + while (repeatCount--) { + [cluster testBatchHelperRequestWithParams:params completion: + ^(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable values, NSError * _Nullable error) { + NSLog(@"Values: %@", values); + if (error == nil) { + constexpr chip::CommandId responseId = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::Id; + RemoteDataModelLogger::LogCommandAsJSON(@(endpointId), @(clusterId), @(responseId), values); + } + responsesNeeded--; + if (error != nil) { + mError = error; + LogNSError("Error", error); + constexpr chip::CommandId responseId = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::Id; + RemoteDataModelLogger::LogCommandErrorAsJSON(@(endpointId), @(clusterId), @(responseId), error); + } + if (responsesNeeded == 0) { + SetCommandExitStatus(mError); + } + }]; + } + return CHIP_NO_ERROR; + } + +private: + chip::app::Clusters::UnitTesting::Commands::TestBatchHelperRequest::Type mRequest; +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL +/* + * Command TestSecondBatchHelperRequest + */ +class UnitTestingTestSecondBatchHelperRequest : public ClusterCommand { +public: + UnitTestingTestSecondBatchHelperRequest() + : ClusterCommand("test-second-batch-helper-request") + { +#if MTR_ENABLE_PROVISIONAL + AddArgument("SleepBeforeResponseTimeMs", 0, UINT16_MAX, &mRequest.sleepBeforeResponseTimeMs); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("SizeOfResponseBuffer", 0, UINT16_MAX, &mRequest.sizeOfResponseBuffer); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("FillCharacter", 0, UINT8_MAX, &mRequest.fillCharacter); +#endif // MTR_ENABLE_PROVISIONAL + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::UnitTesting::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::UnitTesting::Commands::TestSecondBatchHelperRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, commandId, endpointId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRUnitTestingClusterTestSecondBatchHelperRequestParams alloc] init]; + params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; +#if MTR_ENABLE_PROVISIONAL + params.sleepBeforeResponseTimeMs = [NSNumber numberWithUnsignedShort:mRequest.sleepBeforeResponseTimeMs]; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.sizeOfResponseBuffer = [NSNumber numberWithUnsignedShort:mRequest.sizeOfResponseBuffer]; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.fillCharacter = [NSNumber numberWithUnsignedChar:mRequest.fillCharacter]; +#endif // MTR_ENABLE_PROVISIONAL + uint16_t repeatCount = mRepeatCount.ValueOr(1); + uint16_t __block responsesNeeded = repeatCount; + while (repeatCount--) { + [cluster testSecondBatchHelperRequestWithParams:params completion: + ^(MTRUnitTestingClusterTestBatchHelperResponseParams * _Nullable values, NSError * _Nullable error) { + NSLog(@"Values: %@", values); + if (error == nil) { + constexpr chip::CommandId responseId = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::Id; + RemoteDataModelLogger::LogCommandAsJSON(@(endpointId), @(clusterId), @(responseId), values); + } + responsesNeeded--; + if (error != nil) { + mError = error; + LogNSError("Error", error); + constexpr chip::CommandId responseId = chip::app::Clusters::UnitTesting::Commands::TestBatchHelperResponse::Id; + RemoteDataModelLogger::LogCommandErrorAsJSON(@(endpointId), @(clusterId), @(responseId), error); + } + if (responsesNeeded == 0) { + SetCommandExitStatus(mError); + } + }]; + } + return CHIP_NO_ERROR; + } + +private: + chip::app::Clusters::UnitTesting::Commands::TestSecondBatchHelperRequest::Type mRequest; +}; + +#endif // MTR_ENABLE_PROVISIONAL + /* * Attribute Boolean */ @@ -181084,6 +181229,12 @@ void registerClusterUnitTesting(Commands & commands) make_unique(), // make_unique(), // make_unique(), // +#if MTR_ENABLE_PROVISIONAL + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL make_unique(Id), // make_unique(Id), // make_unique(Id), // diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index d67b62285f449e..5a739fd0e02d9f 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -143224,7 +143224,7 @@ class TestCluster : public TestCommandBridge { { id actualValue = value; - VerifyOrReturn(CheckValue("AcceptedCommandList", [actualValue count], static_cast(18))); + VerifyOrReturn(CheckValue("AcceptedCommandList", [actualValue count], static_cast(20))); VerifyOrReturn(CheckValue("", actualValue[0], 0UL)); VerifyOrReturn(CheckValue("", actualValue[1], 1UL)); VerifyOrReturn(CheckValue("", actualValue[2], 2UL)); @@ -143243,6 +143243,8 @@ class TestCluster : public TestCommandBridge { VerifyOrReturn(CheckValue("", actualValue[15], 19UL)); VerifyOrReturn(CheckValue("", actualValue[16], 20UL)); VerifyOrReturn(CheckValue("", actualValue[17], 21UL)); + VerifyOrReturn(CheckValue("", actualValue[18], 22UL)); + VerifyOrReturn(CheckValue("", actualValue[19], 23UL)); } NextTest(); @@ -143269,7 +143271,7 @@ class TestCluster : public TestCommandBridge { { id actualValue = value; - VerifyOrReturn(CheckValue("GeneratedCommandList", [actualValue count], static_cast(9))); + VerifyOrReturn(CheckValue("GeneratedCommandList", [actualValue count], static_cast(10))); VerifyOrReturn(CheckValue("", actualValue[0], 0UL)); VerifyOrReturn(CheckValue("", actualValue[1], 1UL)); VerifyOrReturn(CheckValue("", actualValue[2], 4UL)); @@ -143279,6 +143281,7 @@ class TestCluster : public TestCommandBridge { VerifyOrReturn(CheckValue("", actualValue[6], 9UL)); VerifyOrReturn(CheckValue("", actualValue[7], 10UL)); VerifyOrReturn(CheckValue("", actualValue[8], 11UL)); + VerifyOrReturn(CheckValue("", actualValue[9], 12UL)); } NextTest(); From 649e991b07f0d2f938168977069c01e8e617631e Mon Sep 17 00:00:00 2001 From: arun-silabs <141724790+arun-silabs@users.noreply.github.com> Date: Mon, 8 Jan 2024 23:18:26 +0530 Subject: [PATCH 08/33] Increasing buffer size to avoid memory insufficient error while adding new fabrics. (#31287) --- src/lwip/silabs/lwipopts-rs911x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lwip/silabs/lwipopts-rs911x.h b/src/lwip/silabs/lwipopts-rs911x.h index 72dcd190896c39..3e60b5253eb97a 100644 --- a/src/lwip/silabs/lwipopts-rs911x.h +++ b/src/lwip/silabs/lwipopts-rs911x.h @@ -129,7 +129,7 @@ #define MEMP_SEPARATE_POOLS (1) #define LWIP_PBUF_FROM_CUSTOM_POOLS (0) #define MEMP_USE_CUSTOM_POOLS (0) -#define PBUF_POOL_SIZE (16) +#define PBUF_POOL_SIZE (32) #define PBUF_POOL_BUFSIZE (1280) // IPv6 path MTU #define PBUF_CUSTOM_POOL_IDX_START (MEMP_PBUF_POOL_SMALL) #define PBUF_CUSTOM_POOL_IDX_END (MEMP_PBUF_POOL_LARGE) From 607859f706addb04a3aa5fbad3b49d7c5899cfca Mon Sep 17 00:00:00 2001 From: Matt Hazley Date: Mon, 8 Jan 2024 18:48:40 +0100 Subject: [PATCH 09/33] Add Uncertainty Check to all 2.1 Concentration Measurement Tests (#31290) * Fixes #31263 by adding uncertainty check to all concentration tests * Regen after test change * Restyled by whitespace --------- Co-authored-by: Restyled.io --- .../certification/Test_TC_CDOCONC_2_1.yaml | 9 + .../certification/Test_TC_CMOCONC_2_1.yaml | 9 + .../certification/Test_TC_FLDCONC_2_1.yaml | 9 + .../certification/Test_TC_NDOCONC_2_1.yaml | 9 + .../certification/Test_TC_OZCONC_2_1.yaml | 9 + .../certification/Test_TC_PMHCONC_2_1.yaml | 9 + .../certification/Test_TC_PMICONC_2_1.yaml | 9 + .../certification/Test_TC_PMKCONC_2_1.yaml | 9 + .../certification/Test_TC_RNCONC_2_1.yaml | 9 + .../certification/Test_TC_TVOCCONC_2_1.yaml | 9 + .../zap-generated/test/Commands.h | 380 +++++++++++++++++- 11 files changed, 460 insertions(+), 10 deletions(-) diff --git a/src/app/tests/suites/certification/Test_TC_CDOCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_CDOCONC_2_1.yaml index aefd4aeb36e961..dd3ba305b602bc 100644 --- a/src/app/tests/suites/certification/Test_TC_CDOCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_CDOCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: CDOCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_CMOCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_CMOCONC_2_1.yaml index 9d1ab7f333031e..88fd3646e6b1e0 100644 --- a/src/app/tests/suites/certification/Test_TC_CMOCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_CMOCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: CMOCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_FLDCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_FLDCONC_2_1.yaml index fa75195dd33fff..3a9ca77e47a334 100644 --- a/src/app/tests/suites/certification/Test_TC_FLDCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_FLDCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: FLDCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_NDOCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_NDOCONC_2_1.yaml index 145610ca5ff950..e795b775716df8 100644 --- a/src/app/tests/suites/certification/Test_TC_NDOCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_NDOCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: NDOCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_OZCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_OZCONC_2_1.yaml index d1cf7f692e555a..96223f37b386f5 100644 --- a/src/app/tests/suites/certification/Test_TC_OZCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_OZCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: OZCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_PMHCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_PMHCONC_2_1.yaml index 2e673e96a6899c..4f3d0c36559a45 100644 --- a/src/app/tests/suites/certification/Test_TC_PMHCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_PMHCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: PMHCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_PMICONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_PMICONC_2_1.yaml index f1692efb0443e2..ea0252acda3aee 100644 --- a/src/app/tests/suites/certification/Test_TC_PMICONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_PMICONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: PMICONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_PMKCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_PMKCONC_2_1.yaml index 1045a64fada66c..26d68f04f51954 100644 --- a/src/app/tests/suites/certification/Test_TC_PMKCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_PMKCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: PMKCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_RNCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_RNCONC_2_1.yaml index fe2a4adebcfae9..dffcf2e7b39818 100644 --- a/src/app/tests/suites/certification/Test_TC_RNCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_RNCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: RNCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/src/app/tests/suites/certification/Test_TC_TVOCCONC_2_1.yaml b/src/app/tests/suites/certification/Test_TC_TVOCCONC_2_1.yaml index 578b12c8de855d..a63ecaecfabe5a 100644 --- a/src/app/tests/suites/certification/Test_TC_TVOCCONC_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_TVOCCONC_2_1.yaml @@ -133,3 +133,12 @@ tests: type: enum8 minValue: 0 maxValue: 4 + + - label: "Step 12: TH reads from the DUT the Uncertainty attribute." + PICS: TVOCCONC.S.A0007 + command: "readAttribute" + attribute: "Uncertainty" + response: + constraints: + type: single + minValue: 0 diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index 5a739fd0e02d9f..73c0b07b89b670 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -30012,6 +30012,14 @@ class Test_TC_CDOCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("CDOCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -30056,6 +30064,9 @@ class Test_TC_CDOCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -30066,7 +30077,7 @@ class Test_TC_CDOCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -30361,6 +30372,31 @@ class Test_TC_CDOCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterCarbonDioxideConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_CMOCONC_1_1 : public TestCommandBridge { @@ -31579,6 +31615,14 @@ class Test_TC_CMOCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("CMOCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -31623,6 +31667,9 @@ class Test_TC_CMOCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -31633,7 +31680,7 @@ class Test_TC_CMOCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -31928,6 +31975,31 @@ class Test_TC_CMOCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterCarbonMonoxideConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_FLDCONC_1_1 : public TestCommandBridge { @@ -33146,6 +33218,14 @@ class Test_TC_FLDCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("FLDCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -33190,6 +33270,9 @@ class Test_TC_FLDCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -33200,7 +33283,7 @@ class Test_TC_FLDCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -33495,6 +33578,31 @@ class Test_TC_FLDCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterFormaldehydeConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_NDOCONC_1_1 : public TestCommandBridge { @@ -34713,6 +34821,14 @@ class Test_TC_NDOCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("NDOCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -34757,6 +34873,9 @@ class Test_TC_NDOCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -34767,7 +34886,7 @@ class Test_TC_NDOCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -35062,6 +35181,31 @@ class Test_TC_NDOCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterNitrogenDioxideConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_OZCONC_1_1 : public TestCommandBridge { @@ -36280,6 +36424,14 @@ class Test_TC_OZCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("OZCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -36324,6 +36476,9 @@ class Test_TC_OZCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -36334,7 +36489,7 @@ class Test_TC_OZCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -36629,6 +36784,31 @@ class Test_TC_OZCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterOzoneConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_PMHCONC_1_1 : public TestCommandBridge { @@ -37847,6 +38027,14 @@ class Test_TC_PMHCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("PMHCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -37891,6 +38079,9 @@ class Test_TC_PMHCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -37901,7 +38092,7 @@ class Test_TC_PMHCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -38196,6 +38387,31 @@ class Test_TC_PMHCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterPM1ConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_PMICONC_1_1 : public TestCommandBridge { @@ -39414,6 +39630,14 @@ class Test_TC_PMICONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("PMICONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -39458,6 +39682,9 @@ class Test_TC_PMICONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -39468,7 +39695,7 @@ class Test_TC_PMICONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -39763,6 +39990,31 @@ class Test_TC_PMICONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterPM25ConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_PMKCONC_1_1 : public TestCommandBridge { @@ -40981,6 +41233,14 @@ class Test_TC_PMKCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("PMKCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -41025,6 +41285,9 @@ class Test_TC_PMKCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -41035,7 +41298,7 @@ class Test_TC_PMKCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -41330,6 +41593,31 @@ class Test_TC_PMKCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterPM10ConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_RNCONC_1_1 : public TestCommandBridge { @@ -42548,6 +42836,14 @@ class Test_TC_RNCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("RNCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -42592,6 +42888,9 @@ class Test_TC_RNCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -42602,7 +42901,7 @@ class Test_TC_RNCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -42897,6 +43196,31 @@ class Test_TC_RNCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterRadonConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_TVOCCONC_1_1 : public TestCommandBridge { @@ -44115,6 +44439,14 @@ class Test_TC_TVOCCONC_2_1 : public TestCommandBridge { } err = TestStep11ThReadsFromTheDutTheLevelValueAttribute_10(); break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Step 12: TH reads from the DUT the Uncertainty attribute.\n"); + if (ShouldSkip("TVOCCONC.S.A0007")) { + NextTest(); + return; + } + err = TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11(); + break; } if (CHIP_NO_ERROR != err) { @@ -44159,6 +44491,9 @@ class Test_TC_TVOCCONC_2_1 : public TestCommandBridge { case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -44169,7 +44504,7 @@ class Test_TC_TVOCCONC_2_1 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 11; + const uint16_t mTestCount = 12; chip::Optional mNodeId; chip::Optional mCluster; @@ -44464,6 +44799,31 @@ class Test_TC_TVOCCONC_2_1 : public TestCommandBridge { return CHIP_NO_ERROR; } + + CHIP_ERROR TestStep12ThReadsFromTheDutTheUncertaintyAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterTotalVolatileOrganicCompoundsConcentrationMeasurement alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeUncertaintyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + if (err != nil) { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Error: %@", err); + } else { + NSLog(@"Step 12: TH reads from the DUT the Uncertainty attribute.: Success"); + } + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("uncertainty", "single", "single")); + VerifyOrReturn(CheckConstraintMinValue("uncertainty", [value floatValue], 0.0f)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } }; class Test_TC_OPCREDS_1_2 : public TestCommandBridge { From 7362ccdfb3fdb65d7797bfae3cddbd9a1326cee7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:11:55 +0000 Subject: [PATCH 10/33] Bump third_party/openthread/repo from `ee74513` to `d81c6fa` (#31280) Bumps [third_party/openthread/repo](https://github.com/openthread/openthread) from `ee74513` to `d81c6fa`. - [Release notes](https://github.com/openthread/openthread/releases) - [Commits](https://github.com/openthread/openthread/compare/ee745130c7035c5ea3268b5869cca90a5e434eee...d81c6fab98df8fbeb0f3611ce5ec4c131c84cbce) --- updated-dependencies: - dependency-name: third_party/openthread/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/openthread/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/openthread/repo b/third_party/openthread/repo index ee745130c7035c..d81c6fab98df8f 160000 --- a/third_party/openthread/repo +++ b/third_party/openthread/repo @@ -1 +1 @@ -Subproject commit ee745130c7035c5ea3268b5869cca90a5e434eee +Subproject commit d81c6fab98df8fbeb0f3611ce5ec4c131c84cbce From 6ce2bedd0ad41f30a7efd3a34e4e0220793fadb8 Mon Sep 17 00:00:00 2001 From: Matt Hazley Date: Mon, 8 Jan 2024 19:22:30 +0100 Subject: [PATCH 11/33] Corrects the constraint of FanMode to exclude deprecated values (#31291) * Fixes #31230, corrects the constraint of FanMode to exclude deprecated values * Regen after test change --- src/app/tests/suites/certification/Test_TC_FAN_2_1.yaml | 3 +-- .../darwin-framework-tool/zap-generated/test/Commands.h | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/app/tests/suites/certification/Test_TC_FAN_2_1.yaml b/src/app/tests/suites/certification/Test_TC_FAN_2_1.yaml index 3db36a7578cce4..8f4c23f5c9a301 100644 --- a/src/app/tests/suites/certification/Test_TC_FAN_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_FAN_2_1.yaml @@ -38,8 +38,7 @@ tests: response: constraints: type: enum8 - minValue: 0 - maxValue: 6 + anyOf: [0, 1, 2, 3, 5] - label: "Step 3: TH reads from the DUT the the FanModeSequence attribute" PICS: FAN.S.A0001 diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index 73c0b07b89b670..e697328e97787c 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -50906,9 +50906,6 @@ class Test_TC_FAN_2_1 : public TestCommandBridge { VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); VerifyOrReturn(CheckConstraintType("fanMode", "enum8", "enum8")); - VerifyOrReturn(CheckConstraintMinValue("fanMode", [value unsignedCharValue], 0U)); - VerifyOrReturn(CheckConstraintMaxValue("fanMode", [value unsignedCharValue], 6U)); - NextTest(); }]; From bb655aca021d575bb2a24aaa8aab74444eb44fba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:05:45 -0500 Subject: [PATCH 12/33] Bump third_party/mbedtls/repo from `0071830` to `ffb18d2` (#31285) Bumps [third_party/mbedtls/repo](https://github.com/ARMmbed/mbedtls) from `0071830` to `ffb18d2`. - [Release notes](https://github.com/ARMmbed/mbedtls/releases) - [Commits](https://github.com/ARMmbed/mbedtls/compare/0071830a4fbcc1b38e33a3b001489ccbd9c9e31c...ffb18d2012909c05277a1e16dc6ba23dc8ba2854) --- updated-dependencies: - dependency-name: third_party/mbedtls/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/mbedtls/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/mbedtls/repo b/third_party/mbedtls/repo index 0071830a4fbcc1..ffb18d2012909c 160000 --- a/third_party/mbedtls/repo +++ b/third_party/mbedtls/repo @@ -1 +1 @@ -Subproject commit 0071830a4fbcc1b38e33a3b001489ccbd9c9e31c +Subproject commit ffb18d2012909c05277a1e16dc6ba23dc8ba2854 From 0495db1f35615b8933ae3c6cd65249f61ca742b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:05:58 -0500 Subject: [PATCH 13/33] Bump third_party/ot-br-posix/repo from `1d90133` to `657e775` (#31286) Bumps [third_party/ot-br-posix/repo](https://github.com/openthread/ot-br-posix) from `1d90133` to `657e775`. - [Release notes](https://github.com/openthread/ot-br-posix/releases) - [Commits](https://github.com/openthread/ot-br-posix/compare/1d90133f6656f774ca97840dda6ea3bd04fb4093...657e775cd9ca757af7487da2fb039aee645c3d65) --- updated-dependencies: - dependency-name: third_party/ot-br-posix/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/ot-br-posix/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/ot-br-posix/repo b/third_party/ot-br-posix/repo index 1d90133f6656f7..657e775cd9ca75 160000 --- a/third_party/ot-br-posix/repo +++ b/third_party/ot-br-posix/repo @@ -1 +1 @@ -Subproject commit 1d90133f6656f774ca97840dda6ea3bd04fb4093 +Subproject commit 657e775cd9ca757af7487da2fb039aee645c3d65 From 1f41ed77934058130eb35cfa1b723b148e274a44 Mon Sep 17 00:00:00 2001 From: Anu Biradar <104591549+abiradarti@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:12:34 -0600 Subject: [PATCH 14/33] [TI] CC13xx Factory Data Tool (#31117) * dac tool functionally working for cc13x2 and cc13x4 * updated documentation, added dac tool to all examples * removed old memmap image * code clean up * updated cc13x4 memmap * more code cleanup * added in Thor modifications to oad and factory data merge tool python script * ti_simplelink_executable.gni fix * factory data overlap in ota merge tool fixed * added debug statement in ti simplelink exec * added in custom factory data flag to pump controller * added public creds header files * code review updates and cc13x2 em file fix * fixed pump controller app build issues when using factory data * added back in ota linker file for cc13x4 * spelling fixes * Restyled by whitespace * Restyled by clang-format * Restyled by prettier-markdown * Restyled by autopep8 * Restyled by isort * spelling fix * Restyled by prettier-markdown * pr review feedback * Restyled by clang-format * more pr feedback * empty commit --------- Co-authored-by: Restyled.io --- docs/guides/ti/images/cc13x2_memmap.png | Bin 0 -> 15866 bytes docs/guides/ti/images/cc13x4_memmap.png | Bin 0 -> 21107 bytes .../ti/images/factory_data_overview.png | Bin 0 -> 41408 bytes docs/guides/ti/ti_factory_data_user_guide.md | 127 ++++++ .../all-clusters-app/cc13x2x7_26x2x7/BUILD.gn | 4 + .../all-clusters-app/cc13x2x7_26x2x7/args.gni | 2 + .../cc13x2x7_26x2x7/main/AppTask.cpp | 16 +- .../cc13x2x7_26x2x7/main/include/AppTask.h | 8 + .../all-clusters-app/cc13x4_26x4/BUILD.gn | 4 + .../all-clusters-app/cc13x4_26x4/args.gni | 2 + .../cc13x4_26x4/main/AppTask.cpp | 20 +- .../cc13x4_26x4/main/include/AppTask.h | 8 + .../lighting-app/cc13x2x7_26x2x7/BUILD.gn | 4 + .../lighting-app/cc13x2x7_26x2x7/args.gni | 2 + .../cc13x2x7_26x2x7/src/AppTask.cpp | 20 +- .../cc13x2x7_26x2x7/src/AppTask.h | 8 + examples/lighting-app/cc13x4_26x4/BUILD.gn | 4 + examples/lighting-app/cc13x4_26x4/args.gni | 2 + .../lighting-app/cc13x4_26x4/src/AppTask.cpp | 20 +- .../lighting-app/cc13x4_26x4/src/AppTask.h | 8 + examples/lock-app/cc13x2x7_26x2x7/BUILD.gn | 4 + examples/lock-app/cc13x2x7_26x2x7/args.gni | 2 + .../lock-app/cc13x2x7_26x2x7/main/AppTask.cpp | 394 ------------------ .../cc13x2x7_26x2x7/main/BoltLockManager.cpp | 204 --------- .../cc13x2x7_26x2x7/main/ZclCallbacks.cpp | 56 --- .../cc13x2x7_26x2x7/main/include/AppConfig.h | 34 -- .../cc13x2x7_26x2x7/main/include/AppEvent.h | 60 --- .../cc13x2x7_26x2x7/main/include/AppTask.h | 78 ---- .../main/include/BoltLockManager.h | 87 ---- .../main/include/CHIPProjectConfig.h | 119 ------ .../main/include/OpenThreadConfig.h | 29 -- .../lock-app/cc13x2x7_26x2x7/main/main.cpp | 97 ----- .../lock-app/cc13x2x7_26x2x7/src/AppTask.cpp | 20 +- .../lock-app/cc13x2x7_26x2x7/src/AppTask.h | 8 + examples/lock-app/cc13x4_26x4/BUILD.gn | 4 + examples/lock-app/cc13x4_26x4/args.gni | 3 + examples/lock-app/cc13x4_26x4/src/AppTask.cpp | 20 +- examples/lock-app/cc13x4_26x4/src/AppTask.h | 8 + .../CC13X2_26X2DeviceAttestationCreds.cpp | 12 +- .../CC13X4_26X4DeviceAttestationCreds.cpp | 2 + examples/pump-app/cc13x2x7_26x2x7/BUILD.gn | 4 + examples/pump-app/cc13x2x7_26x2x7/args.gni | 4 + .../pump-app/cc13x2x7_26x2x7/main/AppTask.cpp | 23 +- .../cc13x2x7_26x2x7/main/include/AppTask.h | 8 + examples/pump-app/cc13x4_26x4/BUILD.gn | 4 + examples/pump-app/cc13x4_26x4/args.gni | 8 +- .../pump-app/cc13x4_26x4/main/AppTask.cpp | 20 +- .../cc13x4_26x4/main/include/AppTask.h | 8 + .../cc13x2x7_26x2x7/BUILD.gn | 4 + .../cc13x2x7_26x2x7/args.gni | 2 + .../cc13x2x7_26x2x7/main/AppTask.cpp | 18 +- .../cc13x2x7_26x2x7/main/include/AppTask.h | 8 + .../pump-controller-app/cc13x4_26x4/BUILD.gn | 4 + .../pump-controller-app/cc13x4_26x4/args.gni | 2 + .../cc13x4_26x4/main/AppTask.cpp | 18 +- .../cc13x4_26x4/main/include/AppTask.h | 8 + examples/shell/cc13x2x7_26x2x7/BUILD.gn | 4 + examples/shell/cc13x2x7_26x2x7/args.gni | 2 + .../shell/cc13x2x7_26x2x7/include/AppTask.h | 8 + .../shell/cc13x2x7_26x2x7/main/AppTask.cpp | 17 +- examples/shell/cc13x4_26x4/BUILD.gn | 4 + examples/shell/cc13x4_26x4/args.gni | 2 + examples/shell/cc13x4_26x4/include/AppTask.h | 8 + examples/shell/cc13x4_26x4/main/AppTask.cpp | 16 +- scripts/setup/requirements.ti.txt | 2 + .../cc13xx_26xx/FactoryDataProvider.cpp | 333 +++++++++++++++ .../cc13xx_26xx/FactoryDataProvider.h | 69 +++ src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn | 14 + ...2x7_cc26x2x7_freertos_ota_factory_data.lds | 294 +++++++++++++ src/platform/cc13xx_26xx/cc13x4_26x4/BUILD.gn | 15 + .../cc13x4_26x4/cc13x4_cc26x4_freertos.lds | 2 +- .../cc13x4_cc26x4_freertos_factory_data.lds | 269 ++++++++++++ ...c13x4_cc26x4_freertos_ota_factory_data.lds | 280 +++++++++++++ src/platform/cc13xx_26xx/factory_data.schema | 100 +++++ .../cc13xx_26xx/factory_data_cc13xx_26xx.json | 72 ++++ .../cc13xx_26xx/factory_data_config.gni | 17 + .../ti_simplelink_sdk/create_factory_data.py | 164 ++++++++ .../factory_data_merge_tool.py | 41 ++ .../ti_simplelink_sdk/factory_data_trim.py | 77 ++++ .../oad_and_factory_data_merge_tool.py | 51 +++ .../ti_simplelink_executable.gni | 337 +++++++++++++-- 81 files changed, 2556 insertions(+), 1285 deletions(-) create mode 100644 docs/guides/ti/images/cc13x2_memmap.png create mode 100644 docs/guides/ti/images/cc13x4_memmap.png create mode 100644 docs/guides/ti/images/factory_data_overview.png create mode 100644 docs/guides/ti/ti_factory_data_user_guide.md delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/AppTask.cpp delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/BoltLockManager.cpp delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/ZclCallbacks.cpp delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/include/AppConfig.h delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/include/AppEvent.h delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/include/AppTask.h delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/include/BoltLockManager.h delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/include/CHIPProjectConfig.h delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/include/OpenThreadConfig.h delete mode 100644 examples/lock-app/cc13x2x7_26x2x7/main/main.cpp create mode 100644 src/platform/cc13xx_26xx/FactoryDataProvider.cpp create mode 100644 src/platform/cc13xx_26xx/FactoryDataProvider.h create mode 100644 src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos_ota_factory_data.lds create mode 100644 src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_factory_data.lds create mode 100644 src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_ota_factory_data.lds create mode 100644 src/platform/cc13xx_26xx/factory_data.schema create mode 100644 src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json create mode 100644 src/platform/cc13xx_26xx/factory_data_config.gni create mode 100644 third_party/ti_simplelink_sdk/create_factory_data.py create mode 100644 third_party/ti_simplelink_sdk/factory_data_merge_tool.py create mode 100644 third_party/ti_simplelink_sdk/factory_data_trim.py create mode 100644 third_party/ti_simplelink_sdk/oad_and_factory_data_merge_tool.py diff --git a/docs/guides/ti/images/cc13x2_memmap.png b/docs/guides/ti/images/cc13x2_memmap.png new file mode 100644 index 0000000000000000000000000000000000000000..a89aee7837e3aadf37213254c51e3e82f69b3c90 GIT binary patch literal 15866 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 literal 0 HcmV?d00001 diff --git a/docs/guides/ti/images/cc13x4_memmap.png b/docs/guides/ti/images/cc13x4_memmap.png new file mode 100644 index 0000000000000000000000000000000000000000..4442c6352efbc98bba1fb727aa12bbf3ef96c4c4 GIT binary patch literal 21107 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 ^`~XG0@>9l z#_F|E^;ndOck-aeL=%5vS%{D-G!F|zk;-qL|2edAYqWUq%S#%*vJ-wgTQh??2Q8t$ zv|Hk{g1IWk_{!)@hJqQtAGA;YU(&tm*CyA!JHIQZM*S4A{4!=%)Q2I>7QSTOuJM^WBGk_`jaBp$$#x!eiELK zk3am((igw|JzFsCpoNFh{?5wa3&;yO)6(HcLO=#hj7qP#xSe|mlahD9D04yRGB{1& zFeGp*Yjom?%i`W>pY=VV(B(&wqAuz!Yd9iDYgO9Y7$bIr>t6`I$*@ZOOS!lNLueMH z#4gDddETlx5JDyRYQUY{2g0P>iz2ah>LOC~O*pt>XSu0Z*iXf!gs!=zcM2zG&{>a= zI!j=kP`=5u_V7#2(r2#^(ZsUc*GUx*&%KSg;zQl!>n$j?s`c61mBH_*T-jQt#nV~2 zPI1nW!(_pnk26Ncm*E)n+fM=Hc0XJwJt9S&h>t0pQuv`U`uA?X{6C=5VrTnQ+kZB_ zj#A6PF!>wO5^$%zw78raqNya?soNmOD)G;6Ss^~3paZLSM=3t%w}g306tIWZ2UaX9Z{PrRhoOi8q)+!aiwdCgDj4V#gi6}>#&)@IX- z=m|HbBdjZ~kzNO>p^k1~$1q{V^FWvrEq}NY$nqF)fzaw;rS?$$)L4DvzOG}APj}_$ zs7F<5Iu`NoQcG*R%*OBW9_hFIdJ8oyWKMXI;{Xf%;cY|GdtBJ0adr{I_GRbW-f*AM z7&GI7um$fl`uZi&GX)~P^Na+(N-WW1{x0IqH8VQNu;Q-u_5G-3-P7ca+M+PB2k>Hd zg}$FrUfE!14J8Rf^t$wJA86Ln6!yy}{%WAU^pZ1*MJ~qvqNs~$?)>wr4N;A4{~s`_ zH14%GU-kTqoDkZow|9mUyEcWoGbhG#U*c9iQ~zdGD#6jNV)ufSU;)j=q{4!fmY+48 z!sJ8Q&$Ls~K9!;mci3m+fxTA6n`}Ecl+{mZXOdVx_Sq93|MvT0-iVRMEPQV*Ax$9l zonCm-3O|8F3r^t_R~5V3wrBCzAaedLjy_2wRyXw{eO7S*UF38st-e&o5i2o@ica7lp5}Zd)hV*r6x3;7514iT<9A z>aDtEu2g|qNeSM{;B58EEgOG-LI2?BK~&mO4@{ZgheRB_qt^SVKVeF~XSOqIk#((b z-$7HT)rW&MwjMcD*fRa?A1egpZx*?DEK;-o0h~MFE>afx#!tBC7ky5{ zRj&tz^o-!3)MZMuez^?T0WiC`LWJH-%2^JX-_FK=cf$T3_Xc|jE~X9>-|ADbSEE3- zueUd;)OvA4WOc)FZ-;4jXJL7xb+!A4O0?UF@=;5&({ zVXSG18oH3qJAU6FNfst=-jO`iu^!O3uXAqlD?sGzV5#EE z&l-PgqeX;9Pqntp<|Tz~6}QZONSH(6&1KlPIm#+dV!VBSo7pU)l`-SVGC2R@;*JI4 zH@oyCGp`I~Yej~q=9exH+joA|xs@8hEg=V97KdWz*M8fFfQuN2uPe!zYr_lR+1u!K zmrY#it0Yl5-xfx<)-ZfI&(T{$($qV}-4 z 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 QOQb4}9dR literal 0 HcmV?d00001 diff --git a/docs/guides/ti/ti_factory_data_user_guide.md b/docs/guides/ti/ti_factory_data_user_guide.md new file mode 100644 index 00000000000000..c8168779d17119 --- /dev/null +++ b/docs/guides/ti/ti_factory_data_user_guide.md @@ -0,0 +1,127 @@ +# Texas Instruments Matter Factory Data Programming User Guide + +This document describes how to use the factory data programming feature for +Matter example applications from Texas Instruments. + +## Background + +The Matter specification lists various information elements that are programmed +at the factory. These values do not change and some are unique per device. This +feature enables customers developing Matter products on TI devices to program +this data and use this as a starting point towards developing their factory +programming infrastructure for their Matter devices. + +## Solution Overview: + +TI Matter examples allow the use of factory data in the following two ways: + +- **Example Out of Box Factory Data** : Use TI example DAC values to get + started. This is intended to be used when just starting with Matter or + during development until customer or product specific data is not required. +- **Custom factory data** : Allows users to configure custom factory data via + a JSON file. The custom values are then processed by a script provided by TI + and merged with the Matter application to create a binary that can be + flashed on to devices. + +### Solution Block Diagram + +![Block Diagram](images/factory_data_overview.png) + +Each element is described in more detail below: + +1. Factory Data JSON: This file is located at src/platform/cc13xx_26xx. + Developers can configure this per device. Elements in this file are from the + specification. +2. Matter Application with dummy factory data: Any TI Matter example application +3. `BIM`/MCUBoot: Boot Image Manager/MCUBoot image used for OTA. This is built + with the Matter application and does not require additional build steps from + developers. +4. create_factory_data.py: Processes a factory data JSON file and generates a + hex file with the unique factory data values configured in the JSON file. +5. factory_data_trim.py: When using the custom factory data option, this script + removes the dummy factory data which is required to be able to successfully + compile the application. +6. `oad`\_and_factory_data_merge_tool.py: Merges the factory data hex, Matter + application without factory data and `BIM`/MCUBoot image to generate a + functional hex that can be programmed onto the device. + +## Flash memory layout + +![Memory Layout 1](images/cc13x2_memmap.png) + +![Memory Layout 2](images/cc13x4_memmap.png) + +## How to use + +Out of box factory data location is configured to be on second last page of +flash. For CC13x2, the starting address is `0xAC000`. For CC13x4, the starting +address is `0xFE800`. This can be configured in the linker file. + +To configure: + +1. Linker file: Set the start address for factory data in the linker file being + used by the application + +``` +FLASH_FACTORY_DATA (R) : ORIGIN = 0x000ac000, LENGTH = 0x00000900 +``` + +``` +/* Define base address for the DAC arrays and struct */ + PROVIDE (_factory_data_base_address = + DEFINED(_factory_data_base_address) ? _factory_data_base_address : 0xAC000); +``` + +2. create_factory_data.py: Set the address of the start of the factory data + elements. Refer to the comments in the script. + +``` + # there are 17 elements, each element will need 8 bytes in the struct + # 4 for length of the element, and 4 for the pointer to the element + # factory data starts at 0xAC000 or 0xFE800, so the elements will + # start 136 bytes after the start address + factory_data_dict = json.load(args.factory_data_json_file[0]) + factory_data_schema = json.load(args.factory_data_schema[0]) + + validate(factory_data_dict, factory_data_schema) + factory_data = factory_data_dict['elements'] + + struct_idx = 0 + values_idx = 0 + if device_family == 'cc13x2_26x2': + value_address = 0xAC088 + else: + value_address = 0xFE888 +``` + +``` + if device_family == 'cc13x2_26x2': + subprocess.call(['objcopy', 'temp.bin','--input-target','binary','--output-target', 'ihex', args.factory_data_hex_file, '--change-addresses=0xac000']) + else: + subprocess.call(['objcopy', 'temp.bin','--input-target','binary','--output-target', 'ihex', args.factory_data_hex_file, '--change-addresses=0xfe800']) +``` + +3. In the example's args.gni file, set 'custom_factory_data' to true + +It is recommended to keep a dedicated page (2 pages for CC13x4) for factory +data. + +### Formatting certs and keys for JSON file + +To format the DAC, private key and PAI as hex strings as shown in the Factory +Data JSON file, use the chip-cert tool located at src/tools/chip-cert and run +the _convert-cert_ command, and list -X, or X.509 DER hex encoded format, as the +output format. These strings can then be copied into the JSON file. + +The SPAKE parameters should be converted from base-64 to hex as well before +being copied into the JSON file. + +### Creating images + +The example application can be built using the instructions in the example's +README. The factory data from the JSON file will be formatted into a hex file +that will then be merged into the final executable. The final executable will be +named _{example-application}-`bim`.hex_ for CC13x2 and +_{example-application}-mcuboot.hex_ for CC13x4, and the factory data that was +inputted into the JSON file will be named +_{example-application}-factory-data.hex_. diff --git a/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn b/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn index dec41e71dc265c..f861549db2fcac 100644 --- a/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn +++ b/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn @@ -108,6 +108,10 @@ ti_simplelink_executable("all-clusters-app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${project_dir}/main", diff --git a/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni b/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni index 9228f70c4a0f03..23c3aee1afb0bb 100644 --- a/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni +++ b/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni @@ -50,3 +50,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8006" matter_software_ver = "0x0001" matter_software_ver_str = "1.0d1" + +custom_factory_data = true diff --git a/examples/all-clusters-app/cc13x2x7_26x2x7/main/AppTask.cpp b/examples/all-clusters-app/cc13x2x7_26x2x7/main/AppTask.cpp index 2d5896a236b570..b6b9bf1e8bd8f4 100644 --- a/examples/all-clusters-app/cc13x2x7_26x2x7/main/AppTask.cpp +++ b/examples/all-clusters-app/cc13x2x7_26x2x7/main/AppTask.cpp @@ -230,6 +230,19 @@ int AppTask::Init() ; } + // Initialize device attestation config +#ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + ret = PlatformMgr().StartEventLoopTask(); if (ret != CHIP_NO_ERROR) { @@ -259,9 +272,6 @@ int AppTask::Init() ConfigurationMgr().LogDeviceConfig(); - // Initialize device attestation config - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); - // We only have network commissioning on endpoint 0. emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false); diff --git a/examples/all-clusters-app/cc13x2x7_26x2x7/main/include/AppTask.h b/examples/all-clusters-app/cc13x2x7_26x2x7/main/include/AppTask.h index 002e1b3f70557c..6ab8ca425ddbdf 100644 --- a/examples/all-clusters-app/cc13x2x7_26x2x7/main/include/AppTask.h +++ b/examples/all-clusters-app/cc13x2x7_26x2x7/main/include/AppTask.h @@ -30,6 +30,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + class AppTask { public: @@ -62,6 +66,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn index 0fd26ca07fdc5f..5bb01459551d91 100644 --- a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn +++ b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn @@ -112,6 +112,10 @@ ti_simplelink_executable("all-clusters-app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${project_dir}/main", diff --git a/examples/all-clusters-app/cc13x4_26x4/args.gni b/examples/all-clusters-app/cc13x4_26x4/args.gni index 7c2e2acc9ae809..35d9666f3ed07c 100644 --- a/examples/all-clusters-app/cc13x4_26x4/args.gni +++ b/examples/all-clusters-app/cc13x4_26x4/args.gni @@ -50,3 +50,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8006" matter_software_ver = "0x0001" matter_software_ver_str = "1.0.1+1" + +custom_factory_data = true diff --git a/examples/all-clusters-app/cc13x4_26x4/main/AppTask.cpp b/examples/all-clusters-app/cc13x4_26x4/main/AppTask.cpp index 1ab7b33a03c846..f82436346fc241 100644 --- a/examples/all-clusters-app/cc13x4_26x4/main/AppTask.cpp +++ b/examples/all-clusters-app/cc13x4_26x4/main/AppTask.cpp @@ -246,6 +246,19 @@ int AppTask::Init() ; } +// Initialize device attestation config +#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + // Init ZCL Data Model and start server PLAT_LOG("Initialize Server"); static chip::CommonCaseDeviceServerInitParams initParams; @@ -259,13 +272,6 @@ int AppTask::Init() ConfigurationMgr().LogDeviceConfig(); - // Initialize device attestation config -#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS - SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif - // We only have network commissioning on endpoint 0. emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false); diff --git a/examples/all-clusters-app/cc13x4_26x4/main/include/AppTask.h b/examples/all-clusters-app/cc13x4_26x4/main/include/AppTask.h index 002e1b3f70557c..6ab8ca425ddbdf 100644 --- a/examples/all-clusters-app/cc13x4_26x4/main/include/AppTask.h +++ b/examples/all-clusters-app/cc13x4_26x4/main/include/AppTask.h @@ -30,6 +30,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + class AppTask { public: @@ -62,6 +66,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/lighting-app/cc13x2x7_26x2x7/BUILD.gn b/examples/lighting-app/cc13x2x7_26x2x7/BUILD.gn index 86c9229a05aff3..a745c65a1407cf 100644 --- a/examples/lighting-app/cc13x2x7_26x2x7/BUILD.gn +++ b/examples/lighting-app/cc13x2x7_26x2x7/BUILD.gn @@ -91,6 +91,10 @@ ti_simplelink_executable("lighting_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${chip_root}/examples/providers/", diff --git a/examples/lighting-app/cc13x2x7_26x2x7/args.gni b/examples/lighting-app/cc13x2x7_26x2x7/args.gni index 56695a5ad89396..8f2c82446b1cf0 100644 --- a/examples/lighting-app/cc13x2x7_26x2x7/args.gni +++ b/examples/lighting-app/cc13x2x7_26x2x7/args.gni @@ -49,3 +49,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8005" matter_software_ver = "0x0001" matter_software_ver_str = "1.0d1" + +custom_factory_data = true diff --git a/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.cpp b/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.cpp index c9e8845a4f7323..7d84e656927d09 100644 --- a/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.cpp +++ b/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.cpp @@ -180,6 +180,19 @@ int AppTask::Init() ; } + // Initialize device attestation config +#ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + ret = ThreadStackMgr().InitThreadStack(); if (ret != CHIP_NO_ERROR) { @@ -226,13 +239,6 @@ int AppTask::Init() Server::GetInstance().Init(initParams); - // Initialize device attestation config -#ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS - SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif - // Initialize LEDs PLAT_LOG("Initialize LEDs"); LED_init(); diff --git a/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.h b/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.h index 3d305601bc12f7..c82a122fef4ea8 100644 --- a/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.h +++ b/examples/lighting-app/cc13x2x7_26x2x7/src/AppTask.h @@ -30,6 +30,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + // Application-defined error codes in the CHIP_ERROR space. #define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) #define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) @@ -85,6 +89,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/lighting-app/cc13x4_26x4/BUILD.gn b/examples/lighting-app/cc13x4_26x4/BUILD.gn index 8b24330ea346d2..f4e9ce30d080aa 100644 --- a/examples/lighting-app/cc13x4_26x4/BUILD.gn +++ b/examples/lighting-app/cc13x4_26x4/BUILD.gn @@ -99,6 +99,10 @@ ti_simplelink_executable("lighting_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${chip_root}/examples/providers/", diff --git a/examples/lighting-app/cc13x4_26x4/args.gni b/examples/lighting-app/cc13x4_26x4/args.gni index 4292dcd7982393..c9f4b718ec9aca 100644 --- a/examples/lighting-app/cc13x4_26x4/args.gni +++ b/examples/lighting-app/cc13x4_26x4/args.gni @@ -48,3 +48,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8005" matter_software_ver = "0x0001" matter_software_ver_str = "1.0.1+1" + +custom_factory_data = true diff --git a/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp b/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp index b6cce74ca13aae..94674a1a787a95 100644 --- a/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp @@ -214,6 +214,19 @@ int AppTask::Init() ; } + // Initialize device attestation config +#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + // Init ZCL Data Model and start server PLAT_LOG("Initialize Server"); static CommonCaseDeviceServerInitParams initParams; @@ -225,13 +238,6 @@ int AppTask::Init() Server::GetInstance().Init(initParams); - // Initialize device attestation config -#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS - SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif - // Initialize LEDs PLAT_LOG("Initialize LEDs"); LED_init(); diff --git a/examples/lighting-app/cc13x4_26x4/src/AppTask.h b/examples/lighting-app/cc13x4_26x4/src/AppTask.h index 3d305601bc12f7..c82a122fef4ea8 100644 --- a/examples/lighting-app/cc13x4_26x4/src/AppTask.h +++ b/examples/lighting-app/cc13x4_26x4/src/AppTask.h @@ -30,6 +30,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + // Application-defined error codes in the CHIP_ERROR space. #define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) #define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) @@ -85,6 +89,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/lock-app/cc13x2x7_26x2x7/BUILD.gn b/examples/lock-app/cc13x2x7_26x2x7/BUILD.gn index 1bbb257ceccd33..db4f599aad8f79 100644 --- a/examples/lock-app/cc13x2x7_26x2x7/BUILD.gn +++ b/examples/lock-app/cc13x2x7_26x2x7/BUILD.gn @@ -91,6 +91,10 @@ ti_simplelink_executable("lock_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${chip_root}/examples/providers/", diff --git a/examples/lock-app/cc13x2x7_26x2x7/args.gni b/examples/lock-app/cc13x2x7_26x2x7/args.gni index 8c7a4eb1c448e5..b10e4def1a1a7c 100644 --- a/examples/lock-app/cc13x2x7_26x2x7/args.gni +++ b/examples/lock-app/cc13x2x7_26x2x7/args.gni @@ -49,3 +49,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8006" matter_software_ver = "0x0001" matter_software_ver_str = "1.0d1" + +custom_factory_data = true diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/AppTask.cpp b/examples/lock-app/cc13x2x7_26x2x7/main/AppTask.cpp deleted file mode 100644 index 1988455e958398..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/AppTask.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Texas Instruments Incorporated - * 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 "AppTask.h" -#include "AppConfig.h" -#include "AppEvent.h" -#include - -#include "FreeRTOS.h" - -#include -#include - -#include -#include - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -#include -#include -#include -#include -#include -#endif - -#include -#include - -#include - -#include -#include - -/* syscfg */ -#include - -#define APP_TASK_STACK_SIZE (4096) -#define APP_TASK_PRIORITY 4 -#define APP_EVENT_QUEUE_SIZE 10 - -using namespace ::chip; -using namespace ::chip::Credentials; -using namespace ::chip::DeviceLayer; - -static TaskHandle_t sAppTaskHandle; -static QueueHandle_t sAppEventQueue; - -static LED_Handle sAppRedHandle; -static LED_Handle sAppGreenHandle; -static Button_Handle sAppLeftHandle; -static Button_Handle sAppRightHandle; -static DeviceInfoProviderImpl sExampleDeviceInfoProvider; - -AppTask AppTask::sAppTask; - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -static DefaultOTARequestor sRequestorCore; -static DefaultOTARequestorStorage sRequestorStorage; -static DefaultOTARequestorDriver sRequestorUser; -static BDXDownloader sDownloader; -static OTAImageProcessorImpl sImageProcessor; - -void InitializeOTARequestor(void) -{ - // Initialize and interconnect the Requestor and Image Processor objects - SetRequestorInstance(&sRequestorCore); - - sRequestorStorage.Init(Server::GetInstance().GetPersistentStorage()); - sRequestorCore.Init(Server::GetInstance(), sRequestorStorage, sRequestorUser, sDownloader); - sImageProcessor.SetOTADownloader(&sDownloader); - sDownloader.SetImageProcessorDelegate(&sImageProcessor); - sRequestorUser.Init(&sRequestorCore, &sImageProcessor); -} -#endif - -int AppTask::StartAppTask() -{ - int ret = 0; - - sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); - if (sAppEventQueue == NULL) - { - PLAT_LOG("Failed to allocate app event queue"); - while (true) - ; - } - - // Start App task. - if (xTaskCreate(AppTaskMain, "APP", APP_TASK_STACK_SIZE / sizeof(StackType_t), NULL, APP_TASK_PRIORITY, &sAppTaskHandle) != - pdPASS) - { - PLAT_LOG("Failed to create app task"); - while (true) - ; - } - return ret; -} - -int AppTask::Init() -{ - LED_Params ledParams; - Button_Params buttonParams; - - cc13x2_26x2LogInit(); - - // Init Chip memory management before the stack - Platform::MemoryInit(); - - CHIP_ERROR ret = PlatformMgr().InitChipStack(); - if (ret != CHIP_NO_ERROR) - { - PLAT_LOG("PlatformMgr().InitChipStack() failed"); - while (true) - ; - } - - ret = ThreadStackMgr().InitThreadStack(); - if (ret != CHIP_NO_ERROR) - { - PLAT_LOG("ThreadStackMgr().InitThreadStack() failed"); - while (true) - ; - } -#if CHIP_DEVICE_CONFIG_THREAD_FTD - ret = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); -#else - ret = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); -#endif - if (ret != CHIP_NO_ERROR) - { - PLAT_LOG("ConnectivityMgr().SetThreadDeviceType() failed"); - while (true) - ; - } - - ret = PlatformMgr().StartEventLoopTask(); - if (ret != CHIP_NO_ERROR) - { - PLAT_LOG("PlatformMgr().StartEventLoopTask() failed"); - while (true) - ; - } - - ret = ThreadStackMgrImpl().StartThreadTask(); - if (ret != CHIP_NO_ERROR) - { - PLAT_LOG("ThreadStackMgr().StartThreadTask() failed"); - while (true) - ; - } - - // Init ZCL Data Model and start server - PLAT_LOG("Initialize Server"); - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - - // Initialize info provider - sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); - SetDeviceInfoProvider(&sExampleDeviceInfoProvider); - - chip::Server::GetInstance().Init(initParams); - - // Initialize device attestation config - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); - - // Initialize LEDs - PLAT_LOG("Initialize LEDs"); - LED_init(); - - LED_Params_init(&ledParams); // default PWM LED - sAppRedHandle = LED_open(CONFIG_LED_RED, &ledParams); - LED_setOff(sAppRedHandle); - - LED_Params_init(&ledParams); // default PWM LED - sAppGreenHandle = LED_open(CONFIG_LED_GREEN, &ledParams); - LED_setOff(sAppGreenHandle); - - // Initialize buttons - PLAT_LOG("Initialize buttons"); - Button_init(); - - Button_Params_init(&buttonParams); - buttonParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED; - buttonParams.longPressDuration = 1000U; // ms - sAppLeftHandle = Button_open(CONFIG_BTN_LEFT, &buttonParams); - Button_setCallback(sAppLeftHandle, ButtonLeftEventHandler); - - Button_Params_init(&buttonParams); - buttonParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED; - buttonParams.longPressDuration = 1000U; // ms - sAppRightHandle = Button_open(CONFIG_BTN_RIGHT, &buttonParams); - Button_setCallback(sAppRightHandle, ButtonRightEventHandler); - - // Initialize BoltLock module - PLAT_LOG("Initialize BoltLock"); - BoltLockMgr().Init(); - - BoltLockMgr().SetCallbacks(ActionInitiated, ActionCompleted); - - ConfigurationMgr().LogDeviceConfig(); - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - InitializeOTARequestor(); -#endif - // QR code will be used with CHIP Tool - PrintOnboardingCodes(RendezvousInformationFlags(RendezvousInformationFlag::kBLE)); - - return 0; -} - -void AppTask::AppTaskMain(void * pvParameter) -{ - AppEvent event; - - sAppTask.Init(); - - while (true) - { - /* Task pend until we have stuff to do */ - if (xQueueReceive(sAppEventQueue, &event, portMAX_DELAY) == pdTRUE) - { - sAppTask.DispatchEvent(&event); - } - } -} - -void AppTask::PostEvent(const AppEvent * aEvent) -{ - if (xQueueSend(sAppEventQueue, aEvent, 0) != pdPASS) - { - /* Failed to post the message */ - } -} - -void AppTask::ButtonLeftEventHandler(Button_Handle handle, Button_EventMask events) -{ - AppEvent event; - event.Type = AppEvent::kEventType_ButtonLeft; - - if (events & Button_EV_CLICKED) - { - event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked; - } - else if (events & Button_EV_LONGCLICKED) - { - event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked; - } - // button callbacks are in ISR context - if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS) - { - /* Failed to post the message */ - } -} - -void AppTask::ButtonRightEventHandler(Button_Handle handle, Button_EventMask events) -{ - AppEvent event; - event.Type = AppEvent::kEventType_ButtonRight; - - if (events & Button_EV_CLICKED) - { - event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked; - } - else if (events & Button_EV_LONGCLICKED) - { - event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked; - } - // button callbacks are in ISR context - if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS) - { - /* Failed to post the message */ - } -} - -void AppTask::ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor) -{ - // If the action has been initiated by the lock, update the bolt lock trait - // and start flashing the LEDs rapidly to indicate action initiation. - if (aAction == BoltLockManager::LOCK_ACTION) - { - PLAT_LOG("Lock initiated"); - ; // TODO - } - else if (aAction == BoltLockManager::UNLOCK_ACTION) - { - PLAT_LOG("Unlock initiated"); - ; // TODO - } - - LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); - LED_startBlinking(sAppGreenHandle, 50 /* ms */, LED_BLINK_FOREVER); - LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX); - LED_startBlinking(sAppRedHandle, 110 /* ms */, LED_BLINK_FOREVER); -} - -void AppTask::ActionCompleted(BoltLockManager::Action_t aAction) -{ - // if the action has been completed by the lock, update the bolt lock trait. - // Turn on the lock LED if in a LOCKED state OR - // Turn off the lock LED if in an UNLOCKED state. - if (aAction == BoltLockManager::LOCK_ACTION) - { - PLAT_LOG("Lock completed"); - LED_stopBlinking(sAppGreenHandle); - LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX); - LED_stopBlinking(sAppRedHandle); - LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX); - } - else if (aAction == BoltLockManager::UNLOCK_ACTION) - { - PLAT_LOG("Unlock completed"); - LED_stopBlinking(sAppGreenHandle); - LED_setOff(sAppGreenHandle); - LED_stopBlinking(sAppRedHandle); - LED_setOff(sAppRedHandle); - } -} - -void AppTask::DispatchEvent(AppEvent * aEvent) -{ - switch (aEvent->Type) - { - case AppEvent::kEventType_ButtonLeft: - if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type) - { - if (!BoltLockMgr().IsUnlocked()) - { - BoltLockMgr().InitiateAction(0, BoltLockManager::UNLOCK_ACTION); - } - } - else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type) - { - chip::Server::GetInstance().ScheduleFactoryReset(); - } - break; - - case AppEvent::kEventType_ButtonRight: - if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type) - { - if (BoltLockMgr().IsUnlocked()) - { - BoltLockMgr().InitiateAction(0, BoltLockManager::LOCK_ACTION); - } - } - else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type) - { - // Enable BLE advertisements - if (!ConnectivityMgr().IsBLEAdvertisingEnabled()) - { - if (Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() == CHIP_NO_ERROR) - { - PLAT_LOG("Enabled BLE Advertisements"); - } - else - { - PLAT_LOG("OpenBasicCommissioningWindow() failed"); - } - } - else - { - // Disable BLE advertisements - ConnectivityMgr().SetBLEAdvertisingEnabled(false); - PLAT_LOG("Disabled BLE Advertisements"); - } - } - break; - - case AppEvent::kEventType_AppEvent: - if (NULL != aEvent->Handler) - { - aEvent->Handler(aEvent); - } - break; - - case AppEvent::kEventType_None: - default: - break; - } -} diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/BoltLockManager.cpp b/examples/lock-app/cc13x2x7_26x2x7/main/BoltLockManager.cpp deleted file mode 100644 index b048fc9e9d3f09..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/BoltLockManager.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * 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 "BoltLockManager.h" - -#include "AppConfig.h" -#include "AppTask.h" -#include "FreeRTOS.h" - -#define ACTUATOR_MOVEMENT_PERIOS_MS 500 - -BoltLockManager BoltLockManager::sLock; - -int BoltLockManager::Init() -{ - int ret = 0; - - mTimerHandle = xTimerCreate("BLT_TIMER", pdMS_TO_TICKS(ACTUATOR_MOVEMENT_PERIOS_MS), pdFALSE, this, TimerEventHandler); - if (NULL == mTimerHandle) - { - PLAT_LOG("failed to create bolt lock timer"); - while (true) - ; - } - - mState = kState_LockingCompleted; - mAutoLockTimerArmed = false; - mAutoRelock = false; - mAutoLockDuration = 0; - - return ret; -} - -void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) -{ - mActionInitiated_CB = aActionInitiated_CB; - mActionCompleted_CB = aActionCompleted_CB; -} - -bool BoltLockManager::IsActionInProgress() -{ - return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated); -} - -bool BoltLockManager::IsUnlocked() -{ - return (mState == kState_UnlockingCompleted); -} - -void BoltLockManager::EnableAutoRelock(bool aOn) -{ - mAutoRelock = aOn; -} - -void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs) -{ - mAutoLockDuration = aDurationInSecs; -} - -bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction) -{ - bool action_initiated = false; - State_t new_state; - - // Initiate Lock/Unlock Action only when the previous one is complete. - if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION) - { - action_initiated = true; - - new_state = kState_UnlockingInitiated; - } - else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION) - { - action_initiated = true; - - new_state = kState_LockingInitiated; - } - - if (action_initiated) - { - if (mAutoLockTimerArmed && new_state == kState_LockingInitiated) - { - // If auto lock timer has been armed and someone initiates locking, - // cancel the timer and continue as normal. - mAutoLockTimerArmed = false; - - CancelTimer(); - } - - StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS); - - // Since the timer started successfully, update the state and trigger callback - mState = new_state; - - if (mActionInitiated_CB) - { - mActionInitiated_CB(aAction, aActor); - } - } - - return action_initiated; -} - -void BoltLockManager::StartTimer(uint32_t aTimeoutMs) -{ - xTimerChangePeriod(mTimerHandle, pdMS_TO_TICKS(aTimeoutMs), 100); - xTimerStart(mTimerHandle, 100); -} - -void BoltLockManager::CancelTimer(void) -{ - xTimerStop(mTimerHandle, 100); -} - -void BoltLockManager::TimerEventHandler(TimerHandle_t aTimer) -{ - BoltLockManager * lock = static_cast(pvTimerGetTimerID(aTimer)); - - // The timer event handler will be called in the context of the timer task - // once sLockTimer expires. Post an event to apptask queue with the actual handler - // so that the event can be handled in the context of the apptask. - AppEvent event; - event.Type = AppEvent::kEventType_AppEvent; - event.BoltLockEvent.Context = static_cast(lock); - if (lock->mAutoLockTimerArmed) - { - event.Handler = AutoReLockTimerEventHandler; - } - else - { - event.Handler = ActuatorMovementTimerEventHandler; - } - GetAppTask().PostEvent(&event); -} - -void BoltLockManager::AutoReLockTimerEventHandler(AppEvent * aEvent) -{ - BoltLockManager * lock = static_cast(aEvent->BoltLockEvent.Context); - int32_t actor = 0; - - // Make sure auto lock timer is still armed. - if (!lock->mAutoLockTimerArmed) - { - return; - } - - lock->mAutoLockTimerArmed = false; - - PLAT_LOG("Auto Re-Lock has been triggered!"); - - lock->InitiateAction(actor, LOCK_ACTION); -} - -void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) -{ - Action_t actionCompleted = INVALID_ACTION; - - BoltLockManager * lock = static_cast(aEvent->BoltLockEvent.Context); - - if (lock->mState == kState_LockingInitiated) - { - lock->mState = kState_LockingCompleted; - actionCompleted = LOCK_ACTION; - } - else if (lock->mState == kState_UnlockingInitiated) - { - lock->mState = kState_UnlockingCompleted; - actionCompleted = UNLOCK_ACTION; - } - - if (actionCompleted != INVALID_ACTION) - { - if (lock->mActionCompleted_CB) - { - lock->mActionCompleted_CB(actionCompleted); - } - - if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION) - { - // Start the timer for auto relock - lock->StartTimer(lock->mAutoLockDuration * 1000); - - lock->mAutoLockTimerArmed = true; - - PLAT_LOG("Auto Re-lock enabled. Will be triggered in %u seconds", lock->mAutoLockDuration); - } - } -} diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/ZclCallbacks.cpp b/examples/lock-app/cc13x2x7_26x2x7/main/ZclCallbacks.cpp deleted file mode 100644 index f3b352607c913e..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/ZclCallbacks.cpp +++ /dev/null @@ -1,56 +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. - */ - -#include "AppConfig.h" -#include "BoltLockManager.h" - -#include -#include -#include -#include - -using namespace ::chip; -using namespace ::chip::app::Clusters; - -void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, - uint8_t * value) -{ - if (attributePath.mClusterId == OnOff::Id && attributePath.mAttributeId == OnOff::Attributes::OnOff::Id) - { - BoltLockMgr().InitiateAction(0, *value ? BoltLockManager::LOCK_ACTION : BoltLockManager::UNLOCK_ACTION); - } -} - -/** @brief OnOff Cluster Init - * - * This function is called when a specific cluster is initialized. It gives the - * application an opportunity to take care of cluster initialization procedures. - * It is called exactly once for each endpoint where cluster is present. - * - * @param endpoint Ver.: always - * - * TODO Issue #3841 - * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster - * attributes to the default value. - * The logic here expects something similar to the deprecated Plugins callback - * emberAfPluginOnOffClusterServerPostInitCallback. - * - */ -void emberAfOnOffClusterInitCallback(EndpointId endpoint) -{ - // TODO: implement any additional Cluster Server init actions -} diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/include/AppConfig.h b/examples/lock-app/cc13x2x7_26x2x7/main/include/AppConfig.h deleted file mode 100644 index 3cead418532caa..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/include/AppConfig.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * 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. - */ - -#ifndef APP_CONFIG_H -#define APP_CONFIG_H - -// Logging -#ifdef __cplusplus -extern "C" { -#endif - -int cc13x2_26x2LogInit(void); -void cc13x2_26x2Log(const char * aFormat, ...); -#define PLAT_LOG(...) cc13x2_26x2Log(__VA_ARGS__); - -#ifdef __cplusplus -} -#endif -#endif // APP_CONFIG_H diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/include/AppEvent.h b/examples/lock-app/cc13x2x7_26x2x7/main/include/AppEvent.h deleted file mode 100644 index ad9e93ee3ad1a5..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/include/AppEvent.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright (c) 2018 Nest Labs, Inc. - * 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. - */ - -#ifndef APP_EVENT_H -#define APP_EVENT_H - -struct AppEvent; -typedef void (*EventHandler)(AppEvent *); - -struct AppEvent -{ - enum AppEventType - { - kEventType_None = 0, - kEventType_ButtonLeft, - kEventType_ButtonRight, - kEventType_AppEvent, - }; - - enum AppEventButtonType - { - kAppEventButtonType_None = 0, - kAppEventButtonType_Clicked, - kAppEventButtonType_LongClicked, - }; - - enum AppEventType Type; - - union - { - struct - { - enum AppEventButtonType Type; - } ButtonEvent; - - struct - { - void * Context; - } BoltLockEvent; - }; - - EventHandler Handler; -}; - -#endif // APP_EVENT_H diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/include/AppTask.h b/examples/lock-app/cc13x2x7_26x2x7/main/include/AppTask.h deleted file mode 100644 index 21d552fa89b7d7..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/include/AppTask.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * 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. - */ - -#ifndef APP_TASK_H -#define APP_TASK_H - -#include -#include - -#include "FreeRTOS.h" -#include "semphr.h" -#include "task.h" - -#include "AppEvent.h" -#include "BoltLockManager.h" - -#include - -class AppTask -{ -public: - int StartAppTask(); - static void AppTaskMain(void * pvParameter); - - void PostLockActionRequest(int32_t aActor, BoltLockManager::Action_t aAction); - void PostEvent(const AppEvent * event); - -private: - friend AppTask & GetAppTask(void); - - int Init(); - - // should this be done by BoltLock Manager? I don't want to unravel this spaghetti quite yet - static void ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor); - static void ActionCompleted(BoltLockManager::Action_t aAction); - - void DispatchEvent(AppEvent * event); - - static void ButtonLeftEventHandler(Button_Handle handle, Button_EventMask events); - static void ButtonRightEventHandler(Button_Handle handle, Button_EventMask events); - static void TimerEventHandler(void * p_context); - - enum Function_t - { - kFunction_NoneSelected = 0, - kFunction_SoftwareUpdate = 0, - kFunction_FactoryReset, - - kFunction_Invalid - } Function; - - Function_t mFunction; - bool mFunctionTimerActive; - - static AppTask sAppTask; -}; - -inline AppTask & GetAppTask(void) -{ - return AppTask::sAppTask; -} - -#endif // APP_TASK_H diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/include/BoltLockManager.h b/examples/lock-app/cc13x2x7_26x2x7/main/include/BoltLockManager.h deleted file mode 100644 index 40fc4ffb338a67..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/include/BoltLockManager.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Copyright (c) 2019 Google LLC. - * 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. - */ - -#ifndef LOCK_MANAGER_H -#define LOCK_MANAGER_H - -#include -#include - -#include "AppEvent.h" - -#include -#include - -class BoltLockManager -{ -public: - enum Action_t - { - LOCK_ACTION = 0, - UNLOCK_ACTION, - - INVALID_ACTION - } Action; - - enum State_t - { - kState_LockingInitiated = 0, - kState_LockingCompleted, - kState_UnlockingInitiated, - kState_UnlockingCompleted, - } State; - - int Init(); - bool IsUnlocked(); - void EnableAutoRelock(bool aOn); - void SetAutoLockDuration(uint32_t aDurationInSecs); - bool IsActionInProgress(); - bool InitiateAction(int32_t aActor, Action_t aAction); - - typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); - typedef void (*Callback_fn_completed)(Action_t); - void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); - -private: - friend BoltLockManager & BoltLockMgr(void); - State_t mState; - - Callback_fn_initiated mActionInitiated_CB; - Callback_fn_completed mActionCompleted_CB; - - bool mAutoRelock; - uint32_t mAutoLockDuration; - bool mAutoLockTimerArmed; - TimerHandle_t mTimerHandle; - - void CancelTimer(void); - void StartTimer(uint32_t aTimeoutMs); - - static void TimerEventHandler(TimerHandle_t aTimer); - static void AutoReLockTimerEventHandler(AppEvent * aEvent); - static void ActuatorMovementTimerEventHandler(AppEvent * aEvent); - - static BoltLockManager sLock; -}; - -inline BoltLockManager & BoltLockMgr(void) -{ - return BoltLockManager::sLock; -} - -#endif // LOCK_MANAGER_H diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/include/CHIPProjectConfig.h b/examples/lock-app/cc13x2x7_26x2x7/main/include/CHIPProjectConfig.h deleted file mode 100644 index 424e38a29f7766..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/include/CHIPProjectConfig.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * 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. - */ - -/** - * @file - * Example project configuration file for CHIP. - * - * This is a place to put application or project-specific overrides - * to the default configuration values for general CHIP features. - * - */ - -#ifndef CHIP_PROJECT_CONFIG_H -#define CHIP_PROJECT_CONFIG_H - -#if BUILD_RELEASE // release build -// Note: Default Pairing/PIN/Serial Numbers being used. These should not be enabled for production builds -#endif // BUILD_RELEASE - -// Use a default pairing code if one hasn't been provisioned in flash. -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 - -/** - * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER - * - * Enables the use of a hard-coded default serial number if none - * is found in CHIP NV storage. - */ -#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" - -/** - * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION - * - * The hardware version number assigned to device or product by the device vendor. This - * number is scoped to the device product id, and typically corresponds to a revision of the - * physical device, a change to its packaging, and/or a change to its marketing presentation. - * This value is generally *not* incremented for device software versions. - */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 1 -#endif - -/** - * Values set by args.gni: - * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID - * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING - * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION - */ - -/** - * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE - * - * Enable support for CHIP-over-BLE (CHIPOBLE). - */ -#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1 - -/** - * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE - * - * A size, in bytes, of the individual debug event logging buffer. - */ -#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) - -#define MATTER_CC13X2_26X2_PLATFORM_LOG_ENABLED 1 - -/** - * CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - * - * Enable the OpenThread SRP client to allow for CHIP device discovery. - */ -#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT 1 - -/** - * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE - * - * For a development build, set the default importance of events to be logged as Debug. - * Since debug is the lowest importance level, this means all standard, critical, info and - * debug importance level vi events get logged. - */ -#if BUILD_RELEASE -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production -#else -#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug -#endif // BUILD_RELEASE - -#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 - -/** - * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER - * - * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server. - */ -#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2 - -/** - * @def CHIP_IM_MAX_NUM_WRITE_HANDLER - * - * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server. - */ -#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2 - -#endif // CHIP_PROJECT_CONFIG_H diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/include/OpenThreadConfig.h b/examples/lock-app/cc13x2x7_26x2x7/main/include/OpenThreadConfig.h deleted file mode 100644 index 30f5633cc3bc7f..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/include/OpenThreadConfig.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * 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. - */ - -/** - * @file - * Overrides to default OpenThread configuration. - * - */ - -#pragma once - -// Use the TI-supplied default platform configuration for remainder -#include "openthread-core-cc13x2_26x2-config.h" diff --git a/examples/lock-app/cc13x2x7_26x2x7/main/main.cpp b/examples/lock-app/cc13x2x7_26x2x7/main/main.cpp deleted file mode 100644 index 8311c8990aa5c6..00000000000000 --- a/examples/lock-app/cc13x2x7_26x2x7/main/main.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2020 Texas Instruments Incorporated - * - * 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 - -/* Driver Header files */ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#define TOTAL_ICALL_HEAP_SIZE (0xc800) - -using namespace ::chip; -using namespace ::chip::Inet; -using namespace ::chip::DeviceLayer; - -__attribute__((section(".heap"))) uint8_t GlobalHeapZoneBuffer[TOTAL_ICALL_HEAP_SIZE]; -uint32_t heapSize = TOTAL_ICALL_HEAP_SIZE; - -// ================================================================================ -// FreeRTOS Callbacks -// ================================================================================ -extern "C" void vApplicationStackOverflowHook(void) -{ - while (true) - { - ; - } -} - -// ================================================================================ -// Main Code -// ================================================================================ -int main(void) -{ - Board_init(); - bpool((void *) GlobalHeapZoneBuffer, TOTAL_ICALL_HEAP_SIZE); - - GPIO_init(); - - NVS_init(); - - UART_init(); - - ECDH_init(); - - ECDSA_init(); - - AESECB_init(); - - SHA2_init(); - - int ret = GetAppTask().StartAppTask(); - if (ret != 0) - { - // can't log until the kernel is started - // PLAT_LOG("GetAppTask().StartAppTask() failed"); - while (true) - ; - } - - vTaskStartScheduler(); - - // Should never get here. - while (true) - ; -} diff --git a/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.cpp b/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.cpp index d4e3d8f17f42db..380b05e32ca668 100644 --- a/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.cpp +++ b/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.cpp @@ -210,6 +210,19 @@ int AppTask::Init() ; } + // Initialize device attestation config +#ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + // Init ZCL Data Model and start server PLAT_LOG("Initialize Server"); static CommonCaseDeviceServerInitParams initParams; @@ -221,13 +234,6 @@ int AppTask::Init() Server::GetInstance().Init(initParams); - // Initialize device attestation config -#ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS - SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif - // Initialize LEDs PLAT_LOG("Initialize LEDs"); LED_init(); diff --git a/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.h b/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.h index 15939e6581737b..7778fd5f2a5e1f 100644 --- a/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.h +++ b/examples/lock-app/cc13x2x7_26x2x7/src/AppTask.h @@ -30,6 +30,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + // Application-defined error codes in the CHIP_ERROR space. #define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) #define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) @@ -84,6 +88,10 @@ class AppTask bool mSyncClusterToButtonAction; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/lock-app/cc13x4_26x4/BUILD.gn b/examples/lock-app/cc13x4_26x4/BUILD.gn index d7ec4065ea098f..67560cd7469f41 100644 --- a/examples/lock-app/cc13x4_26x4/BUILD.gn +++ b/examples/lock-app/cc13x4_26x4/BUILD.gn @@ -95,6 +95,10 @@ ti_simplelink_executable("lock_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${chip_root}/examples/providers/", diff --git a/examples/lock-app/cc13x4_26x4/args.gni b/examples/lock-app/cc13x4_26x4/args.gni index 2db85d82d398d3..d7508aaa640661 100644 --- a/examples/lock-app/cc13x4_26x4/args.gni +++ b/examples/lock-app/cc13x4_26x4/args.gni @@ -48,4 +48,7 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8006" matter_software_ver = "0x0001" matter_software_ver_str = "1.0.1+1" + # should be maj.min.rev+build with later parts optional for MCUBoot + +custom_factory_data = true diff --git a/examples/lock-app/cc13x4_26x4/src/AppTask.cpp b/examples/lock-app/cc13x4_26x4/src/AppTask.cpp index c73fd1f3909100..c42d06c705d846 100644 --- a/examples/lock-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/lock-app/cc13x4_26x4/src/AppTask.cpp @@ -209,6 +209,19 @@ int AppTask::Init() ; } + // Initialize device attestation config +#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + // Init ZCL Data Model and start server PLAT_LOG("Initialize Server"); static CommonCaseDeviceServerInitParams initParams; @@ -220,13 +233,6 @@ int AppTask::Init() Server::GetInstance().Init(initParams); - // Initialize device attestation config -#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS - SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif - // Initialize LEDs PLAT_LOG("Initialize LEDs"); LED_init(); diff --git a/examples/lock-app/cc13x4_26x4/src/AppTask.h b/examples/lock-app/cc13x4_26x4/src/AppTask.h index 15939e6581737b..7778fd5f2a5e1f 100644 --- a/examples/lock-app/cc13x4_26x4/src/AppTask.h +++ b/examples/lock-app/cc13x4_26x4/src/AppTask.h @@ -30,6 +30,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + // Application-defined error codes in the CHIP_ERROR space. #define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) #define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) @@ -84,6 +88,10 @@ class AppTask bool mSyncClusterToButtonAction; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/platform/cc13x2_26x2/CC13X2_26X2DeviceAttestationCreds.cpp b/examples/platform/cc13x2_26x2/CC13X2_26X2DeviceAttestationCreds.cpp index 46db7a1aaa2670..aa3469b030f4c7 100644 --- a/examples/platform/cc13x2_26x2/CC13X2_26X2DeviceAttestationCreds.cpp +++ b/examples/platform/cc13x2_26x2/CC13X2_26X2DeviceAttestationCreds.cpp @@ -27,11 +27,6 @@ namespace Credentials { namespace CC13X2_26X2 { namespace { - -extern "C" { - -extern void cc13x2_26x2Log(const char * aFormat, ...); - typedef struct { const uint32_t len; @@ -50,12 +45,14 @@ const uint8_t gDacPrivKey[] = { 0x50, 0x5a, 0x21, 0x1d, 0xbd, 0xa8, 0x71, 0x33, 0x0d, 0x63, 0x5d, 0xa3, 0xb0, 0x7e, 0xb1, 0xc5, 0x08, 0x8a, 0x8f, 0xc7, 0x01, 0x24, 0xfb, 0xb3, 0x3e, 0x93, 0xd5, 0x06, 0x05, 0x82, 0xc7, 0xc5, }; + const uint8_t gDacPubKey[] = { 0x04, 0xc5, 0x65, 0xfd, 0xad, 0xfd, 0x16, 0xdd, 0x62, 0xe4, 0x3f, 0x19, 0x60, 0xb9, 0x93, 0xbb, 0x57, 0x2c, 0xfd, 0xd8, 0x1f, 0x6d, 0x71, 0x67, 0x67, 0x1b, 0x77, 0x45, 0xdc, 0xbe, 0x6f, 0x65, 0xaf, 0x66, 0x5a, 0x1d, 0x93, 0x1c, 0x05, 0xb9, 0xf9, 0xa3, 0xe9, 0x45, 0x66, 0x85, 0x60, 0x2c, 0x05, 0xc6, 0x96, 0x46, 0xb8, 0xf7, 0x59, 0x98, 0xdb, 0xaa, 0x68, 0x7a, 0x5c, 0x56, 0x49, 0x02, 0xda, }; + const uint8_t gDacCert[] = { 0x30, 0x82, 0x01, 0xf7, 0x30, 0x82, 0x01, 0x9d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x46, 0x88, 0xeb, 0x94, 0xad, 0x32, 0xb2, 0xe4, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x4d, 0x31, 0x1f, 0x30, 0x1d, 0x06, @@ -110,7 +107,8 @@ const uint8_t gPaiCert[] = { 0xd7, 0xdf, 0xea, 0x3f, 0x4d, 0xa4, 0x6f, 0x35, 0x7a, 0xfe, 0xac, 0xb8, 0x9b, 0x26, 0x77, 0x06, 0xd2, 0x8a, }; -const factoryData gFactoryData = { +const factoryData gFactoryData = +{ .dac_priv_key = { .len = sizeof(gDacPrivKey), .data = gDacPrivKey, @@ -129,8 +127,6 @@ const factoryData gFactoryData = { }, }; -} // extern "C" - CHIP_ERROR LoadKeypairFromRaw(ByteSpan private_key, ByteSpan public_key, Crypto::P256Keypair & keypair) { Crypto::P256SerializedKeypair serialized_keypair; diff --git a/examples/platform/cc13x4_26x4/CC13X4_26X4DeviceAttestationCreds.cpp b/examples/platform/cc13x4_26x4/CC13X4_26X4DeviceAttestationCreds.cpp index 2bbc7cb1829ab2..2cd36b6a14e93f 100644 --- a/examples/platform/cc13x4_26x4/CC13X4_26X4DeviceAttestationCreds.cpp +++ b/examples/platform/cc13x4_26x4/CC13X4_26X4DeviceAttestationCreds.cpp @@ -50,12 +50,14 @@ const uint8_t gDacPrivKey[] = { 0x50, 0x5a, 0x21, 0x1d, 0xbd, 0xa8, 0x71, 0x33, 0x0d, 0x63, 0x5d, 0xa3, 0xb0, 0x7e, 0xb1, 0xc5, 0x08, 0x8a, 0x8f, 0xc7, 0x01, 0x24, 0xfb, 0xb3, 0x3e, 0x93, 0xd5, 0x06, 0x05, 0x82, 0xc7, 0xc5, }; + const uint8_t gDacPubKey[] = { 0x04, 0xc5, 0x65, 0xfd, 0xad, 0xfd, 0x16, 0xdd, 0x62, 0xe4, 0x3f, 0x19, 0x60, 0xb9, 0x93, 0xbb, 0x57, 0x2c, 0xfd, 0xd8, 0x1f, 0x6d, 0x71, 0x67, 0x67, 0x1b, 0x77, 0x45, 0xdc, 0xbe, 0x6f, 0x65, 0xaf, 0x66, 0x5a, 0x1d, 0x93, 0x1c, 0x05, 0xb9, 0xf9, 0xa3, 0xe9, 0x45, 0x66, 0x85, 0x60, 0x2c, 0x05, 0xc6, 0x96, 0x46, 0xb8, 0xf7, 0x59, 0x98, 0xdb, 0xaa, 0x68, 0x7a, 0x5c, 0x56, 0x49, 0x02, 0xda, }; + const uint8_t gDacCert[] = { 0x30, 0x82, 0x01, 0xf7, 0x30, 0x82, 0x01, 0x9d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x46, 0x88, 0xeb, 0x94, 0xad, 0x32, 0xb2, 0xe4, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x4d, 0x31, 0x1f, 0x30, 0x1d, 0x06, diff --git a/examples/pump-app/cc13x2x7_26x2x7/BUILD.gn b/examples/pump-app/cc13x2x7_26x2x7/BUILD.gn index 525133b1f6aa90..4c670552dc2baf 100644 --- a/examples/pump-app/cc13x2x7_26x2x7/BUILD.gn +++ b/examples/pump-app/cc13x2x7_26x2x7/BUILD.gn @@ -91,6 +91,10 @@ ti_simplelink_executable("pump_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${project_dir}/main", diff --git a/examples/pump-app/cc13x2x7_26x2x7/args.gni b/examples/pump-app/cc13x2x7_26x2x7/args.gni index aeeb0708a235e7..1467940fa222ee 100644 --- a/examples/pump-app/cc13x2x7_26x2x7/args.gni +++ b/examples/pump-app/cc13x2x7_26x2x7/args.gni @@ -47,3 +47,7 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x800A" matter_software_ver = "0x0001" matter_software_ver_str = "1.0d1" + +chip_openthread_ftd = false + +custom_factory_data = true diff --git a/examples/pump-app/cc13x2x7_26x2x7/main/AppTask.cpp b/examples/pump-app/cc13x2x7_26x2x7/main/AppTask.cpp index 625d48392f59a8..38f248093548cf 100644 --- a/examples/pump-app/cc13x2x7_26x2x7/main/AppTask.cpp +++ b/examples/pump-app/cc13x2x7_26x2x7/main/AppTask.cpp @@ -207,6 +207,19 @@ int AppTask::Init() sAppRightHandle = Button_open(CONFIG_BTN_RIGHT, &buttonParams); Button_setCallback(sAppRightHandle, ButtonRightEventHandler); + // Initialize device attestation config +#ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + // Initialize Pump module PLAT_LOG("Initialize Pump"); PumpMgr().Init(); @@ -222,15 +235,11 @@ int AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); chip::Server::GetInstance().Init(initParams); - // Initialize device attestation config -#ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS - SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif - ConfigurationMgr().LogDeviceConfig(); + uint32_t iterationCount; + mFactoryDataProvider.GetSpake2pIterationCount(iterationCount); + #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR InitializeOTARequestor(); #endif diff --git a/examples/pump-app/cc13x2x7_26x2x7/main/include/AppTask.h b/examples/pump-app/cc13x2x7_26x2x7/main/include/AppTask.h index 7fd3f38ff6f0d5..47b4fd56f2d671 100644 --- a/examples/pump-app/cc13x2x7_26x2x7/main/include/AppTask.h +++ b/examples/pump-app/cc13x2x7_26x2x7/main/include/AppTask.h @@ -31,6 +31,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + struct Identify; class AppTask @@ -79,6 +83,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/pump-app/cc13x4_26x4/BUILD.gn b/examples/pump-app/cc13x4_26x4/BUILD.gn index f3fc4384f69336..7cbf21cc41140e 100644 --- a/examples/pump-app/cc13x4_26x4/BUILD.gn +++ b/examples/pump-app/cc13x4_26x4/BUILD.gn @@ -99,6 +99,10 @@ ti_simplelink_executable("pump_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${project_dir}/main", diff --git a/examples/pump-app/cc13x4_26x4/args.gni b/examples/pump-app/cc13x4_26x4/args.gni index 66e2a5a2e64ed0..05c67f203ca2a9 100644 --- a/examples/pump-app/cc13x4_26x4/args.gni +++ b/examples/pump-app/cc13x4_26x4/args.gni @@ -33,9 +33,9 @@ openthread_external_platform = "${chip_root}/third_party/openthread/platforms/cc chip_openthread_ftd = true # Disable CHIP Logging -#chip_progress_logging = false -#chip_detail_logging = false -#chip_automation_logging = false +chip_progress_logging = true +chip_detail_logging = true +chip_automation_logging = true # BLE options chip_config_network_layer_ble = true @@ -48,3 +48,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x800A" matter_software_ver = "0x0001" matter_software_ver_str = "1.0.1+1" + +custom_factory_data = true diff --git a/examples/pump-app/cc13x4_26x4/main/AppTask.cpp b/examples/pump-app/cc13x4_26x4/main/AppTask.cpp index 8611b750f80a34..c6e6d766c7e42d 100644 --- a/examples/pump-app/cc13x4_26x4/main/AppTask.cpp +++ b/examples/pump-app/cc13x4_26x4/main/AppTask.cpp @@ -207,6 +207,19 @@ int AppTask::Init() sAppRightHandle = Button_open(CONFIG_BTN_RIGHT, &buttonParams); Button_setCallback(sAppRightHandle, ButtonRightEventHandler); + // Initialize device attestation config +#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else + SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + // Initialize Pump module PLAT_LOG("Initialize Pump"); PumpMgr().Init(); @@ -222,13 +235,6 @@ int AppTask::Init() (void) initParams.InitializeStaticResourcesBeforeServerInit(); chip::Server::GetInstance().Init(initParams); - // Initialize device attestation config -#ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS - SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif - ConfigurationMgr().LogDeviceConfig(); #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR diff --git a/examples/pump-app/cc13x4_26x4/main/include/AppTask.h b/examples/pump-app/cc13x4_26x4/main/include/AppTask.h index 7fd3f38ff6f0d5..47b4fd56f2d671 100644 --- a/examples/pump-app/cc13x4_26x4/main/include/AppTask.h +++ b/examples/pump-app/cc13x4_26x4/main/include/AppTask.h @@ -31,6 +31,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + struct Identify; class AppTask @@ -79,6 +83,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/pump-controller-app/cc13x2x7_26x2x7/BUILD.gn b/examples/pump-controller-app/cc13x2x7_26x2x7/BUILD.gn index 8d0d2d4c72d612..fb118046b876c4 100644 --- a/examples/pump-controller-app/cc13x2x7_26x2x7/BUILD.gn +++ b/examples/pump-controller-app/cc13x2x7_26x2x7/BUILD.gn @@ -90,6 +90,10 @@ ti_simplelink_executable("pump_controller_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${project_dir}/main", diff --git a/examples/pump-controller-app/cc13x2x7_26x2x7/args.gni b/examples/pump-controller-app/cc13x2x7_26x2x7/args.gni index fb13057bc99474..d78851719f1fb5 100644 --- a/examples/pump-controller-app/cc13x2x7_26x2x7/args.gni +++ b/examples/pump-controller-app/cc13x2x7_26x2x7/args.gni @@ -47,3 +47,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8011" matter_software_ver = "0x0001" matter_software_ver_str = "1.0d1" + +custom_factory_data = true diff --git a/examples/pump-controller-app/cc13x2x7_26x2x7/main/AppTask.cpp b/examples/pump-controller-app/cc13x2x7_26x2x7/main/AppTask.cpp index cc59f4daee7b26..0650341acbc081 100644 --- a/examples/pump-controller-app/cc13x2x7_26x2x7/main/AppTask.cpp +++ b/examples/pump-controller-app/cc13x2x7_26x2x7/main/AppTask.cpp @@ -176,19 +176,25 @@ int AppTask::Init() ; } - // Init ZCL Data Model and start server - PLAT_LOG("Initialize Server"); - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - chip::Server::GetInstance().Init(initParams); - // Initialize device attestation config #ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); +#endif #else SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); #endif + // Init ZCL Data Model and start server + PLAT_LOG("Initialize Server"); + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + chip::Server::GetInstance().Init(initParams); + // Initialize LEDs PLAT_LOG("Initialize LEDs"); LED_init(); diff --git a/examples/pump-controller-app/cc13x2x7_26x2x7/main/include/AppTask.h b/examples/pump-controller-app/cc13x2x7_26x2x7/main/include/AppTask.h index bf13d20bca6ee6..bb815585471add 100644 --- a/examples/pump-controller-app/cc13x2x7_26x2x7/main/include/AppTask.h +++ b/examples/pump-controller-app/cc13x2x7_26x2x7/main/include/AppTask.h @@ -31,6 +31,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + struct Identify; class AppTask @@ -74,6 +78,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/pump-controller-app/cc13x4_26x4/BUILD.gn b/examples/pump-controller-app/cc13x4_26x4/BUILD.gn index 95fa5205a3dd67..c1b106f0feb1c2 100644 --- a/examples/pump-controller-app/cc13x4_26x4/BUILD.gn +++ b/examples/pump-controller-app/cc13x4_26x4/BUILD.gn @@ -98,6 +98,10 @@ ti_simplelink_executable("pump_controller_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "${project_dir}", "${project_dir}/main", diff --git a/examples/pump-controller-app/cc13x4_26x4/args.gni b/examples/pump-controller-app/cc13x4_26x4/args.gni index 375ff1b7b08ffb..e2beed52434bcf 100644 --- a/examples/pump-controller-app/cc13x4_26x4/args.gni +++ b/examples/pump-controller-app/cc13x4_26x4/args.gni @@ -48,3 +48,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8011" matter_software_ver = "0x0001" matter_software_ver_str = "1.0.1+1" + +custom_factory_data = true diff --git a/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp b/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp index b51878e64651b6..a8a61bda096d22 100644 --- a/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp +++ b/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp @@ -176,19 +176,25 @@ int AppTask::Init() ; } - // Init ZCL Data Model and start server - PLAT_LOG("Initialize Server"); - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - chip::Server::GetInstance().Init(initParams); - // Initialize device attestation config #ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); +#endif #else SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); #endif + // Init ZCL Data Model and start server + PLAT_LOG("Initialize Server"); + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + chip::Server::GetInstance().Init(initParams); + // Initialize LEDs PLAT_LOG("Initialize LEDs"); LED_init(); diff --git a/examples/pump-controller-app/cc13x4_26x4/main/include/AppTask.h b/examples/pump-controller-app/cc13x4_26x4/main/include/AppTask.h index bf13d20bca6ee6..bb815585471add 100644 --- a/examples/pump-controller-app/cc13x4_26x4/main/include/AppTask.h +++ b/examples/pump-controller-app/cc13x4_26x4/main/include/AppTask.h @@ -31,6 +31,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + struct Identify; class AppTask @@ -74,6 +78,10 @@ class AppTask bool mFunctionTimerActive; static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/shell/cc13x2x7_26x2x7/BUILD.gn b/examples/shell/cc13x2x7_26x2x7/BUILD.gn index 45351e854e6150..5264bd079c02b0 100644 --- a/examples/shell/cc13x2x7_26x2x7/BUILD.gn +++ b/examples/shell/cc13x2x7_26x2x7/BUILD.gn @@ -99,6 +99,10 @@ ti_simplelink_executable("shell_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "include", "main", diff --git a/examples/shell/cc13x2x7_26x2x7/args.gni b/examples/shell/cc13x2x7_26x2x7/args.gni index 92dd1dcdfdd0b2..7a2a55a580dd24 100644 --- a/examples/shell/cc13x2x7_26x2x7/args.gni +++ b/examples/shell/cc13x2x7_26x2x7/args.gni @@ -50,3 +50,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8006" matter_software_ver = "0x0001" matter_software_ver_str = "1.0d1" + +custom_factory_data = true diff --git a/examples/shell/cc13x2x7_26x2x7/include/AppTask.h b/examples/shell/cc13x2x7_26x2x7/include/AppTask.h index 3fe4f972427717..e9426478b5af61 100644 --- a/examples/shell/cc13x2x7_26x2x7/include/AppTask.h +++ b/examples/shell/cc13x2x7_26x2x7/include/AppTask.h @@ -27,6 +27,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + class AppTask { public: @@ -39,6 +43,10 @@ class AppTask CHIP_ERROR Init(); static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/shell/cc13x2x7_26x2x7/main/AppTask.cpp b/examples/shell/cc13x2x7_26x2x7/main/AppTask.cpp index 0c30a0e34c55fb..701e86fed40e05 100644 --- a/examples/shell/cc13x2x7_26x2x7/main/AppTask.cpp +++ b/examples/shell/cc13x2x7_26x2x7/main/AppTask.cpp @@ -144,19 +144,24 @@ CHIP_ERROR AppTask::Init() while (true) ; } - - // Init ZCL Data Model and start server - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - chip::Server::GetInstance().Init(initParams); - // Initialize device attestation config #ifdef CC13X2_26X2_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else SetDeviceAttestationCredentialsProvider(CC13X2_26X2::GetCC13X2_26X2DacProvider()); +#endif #else SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); #endif + // Init ZCL Data Model and start server + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + chip::Server::GetInstance().Init(initParams); + #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR InitializeOTARequestor(); #endif diff --git a/examples/shell/cc13x4_26x4/BUILD.gn b/examples/shell/cc13x4_26x4/BUILD.gn index 1b950f20f1d9bc..e6db696baa649c 100644 --- a/examples/shell/cc13x4_26x4/BUILD.gn +++ b/examples/shell/cc13x4_26x4/BUILD.gn @@ -98,6 +98,10 @@ ti_simplelink_executable("shell_app") { deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] } + if (custom_factory_data) { + defines = [ "CC13XX_26XX_FACTORY_DATA" ] + } + include_dirs = [ "include", "main", diff --git a/examples/shell/cc13x4_26x4/args.gni b/examples/shell/cc13x4_26x4/args.gni index 13e622146a320e..6726b735b8e43a 100644 --- a/examples/shell/cc13x4_26x4/args.gni +++ b/examples/shell/cc13x4_26x4/args.gni @@ -49,3 +49,5 @@ matter_device_vid = "0xFFF1" matter_device_pid = "0x8006" matter_software_ver = "0x0001" matter_software_ver_str = "1.0.1+1" + +custom_factory_data = true diff --git a/examples/shell/cc13x4_26x4/include/AppTask.h b/examples/shell/cc13x4_26x4/include/AppTask.h index 3fe4f972427717..e9426478b5af61 100644 --- a/examples/shell/cc13x4_26x4/include/AppTask.h +++ b/examples/shell/cc13x4_26x4/include/AppTask.h @@ -27,6 +27,10 @@ #include +#ifdef CC13XX_26XX_FACTORY_DATA +#include +#endif + class AppTask { public: @@ -39,6 +43,10 @@ class AppTask CHIP_ERROR Init(); static AppTask sAppTask; + +#ifdef CC13XX_26XX_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif }; inline AppTask & GetAppTask(void) diff --git a/examples/shell/cc13x4_26x4/main/AppTask.cpp b/examples/shell/cc13x4_26x4/main/AppTask.cpp index 1ae57e8cc471b8..2c6aadaef69772 100644 --- a/examples/shell/cc13x4_26x4/main/AppTask.cpp +++ b/examples/shell/cc13x4_26x4/main/AppTask.cpp @@ -150,18 +150,24 @@ CHIP_ERROR AppTask::Init() ; } - // Init ZCL Data Model and start server - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - chip::Server::GetInstance().Init(initParams); - // Initialize device attestation config #ifdef CC13X4_26X4_ATTESTATION_CREDENTIALS +#ifdef CC13XX_26XX_FACTORY_DATA + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); +#else SetDeviceAttestationCredentialsProvider(CC13X4_26X4::GetCC13X4_26X4DacProvider()); +#endif #else SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); #endif + // Init ZCL Data Model and start server + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + chip::Server::GetInstance().Init(initParams); + #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR InitializeOTARequestor(); #endif diff --git a/scripts/setup/requirements.ti.txt b/scripts/setup/requirements.ti.txt index 07f5e30471f1c1..7a6b48fb896bef 100644 --- a/scripts/setup/requirements.ti.txt +++ b/scripts/setup/requirements.ti.txt @@ -3,3 +3,5 @@ click cryptography>=2.6 ecdsa>=0.17.0 intelhex +jsonschema +ecdsa \ No newline at end of file diff --git a/src/platform/cc13xx_26xx/FactoryDataProvider.cpp b/src/platform/cc13xx_26xx/FactoryDataProvider.cpp new file mode 100644 index 00000000000000..695d7e5f757f39 --- /dev/null +++ b/src/platform/cc13xx_26xx/FactoryDataProvider.cpp @@ -0,0 +1,333 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FactoryDataProvider.h" +#include +#include +#include +#include + +namespace chip { +namespace DeviceLayer { + +typedef struct +{ + uint32_t len; + uint8_t * data; +} data_ptr; + +typedef struct +{ + data_ptr serial_number; + data_ptr vendor_id; + data_ptr product_id; + data_ptr vendor_name; + data_ptr product_name; + data_ptr manufacturing_date; + data_ptr hw_ver; + data_ptr hw_ver_str; + data_ptr dac_cert; + data_ptr dac_priv_key; + data_ptr pai_cert; + data_ptr rd_uniqueid; + data_ptr spake2p_it; + data_ptr spake2p_salt; + data_ptr spake2p_verifier; + data_ptr discriminator; + data_ptr passcode; +} factoryData; + +#if defined(__GNUC__) +factoryData __attribute__((section(".factory_data_struct"))) __attribute__((used)) mFactoryData = +#else + +#error "compiler currently not supported" + +#endif + {}; + +CHIP_ERROR LoadKeypairFromRaw(ByteSpan private_key, ByteSpan public_key, Crypto::P256Keypair & keypair) +{ + Crypto::P256SerializedKeypair serialized_keypair; + ReturnErrorOnFailure(serialized_keypair.SetLength(private_key.size() + public_key.size())); + memcpy(serialized_keypair.Bytes(), public_key.data(), public_key.size()); + memcpy(serialized_keypair.Bytes() + public_key.size(), private_key.data(), private_key.size()); + return keypair.Deserialize(serialized_keypair); +} + +CHIP_ERROR FactoryDataProvider::Init() +{ + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetCertificationDeclaration(MutableByteSpan & out_buffer) +{ + //-> format_version = 1 + //-> vendor_id = 0xFFF1 + //-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, + // 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, + // 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, + // 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, + // 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, + // 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, + // 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] + //-> device_type_id = 0x0016 + //-> certificate_id = "ZIG20142ZB330003-24" + //-> security_level = 0 + //-> security_information = 0 + //-> version_number = 0x2694 + //-> certification_type = 0 + //-> dac_origin_vendor_id is not present + //-> dac_origin_product_id is not present + static const uint8_t kCdForAllExamples[] = { + 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, + 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x62, + 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80, + 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, 0x07, 0x80, 0x05, 0x08, + 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, 0x80, 0x05, 0x0e, 0x80, 0x05, + 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, + 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, + 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, + 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, + 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, + 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, + 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, + 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, + 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, + 0x4b, 0x80, 0x05, 0x4c, 0x80, 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, + 0x05, 0x52, 0x80, 0x05, 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, + 0x80, 0x05, 0x59, 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, + 0x5f, 0x80, 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, + 0x13, 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, + 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, + 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, + 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, 0xd1, 0xf4, 0x7a, 0x7d, + 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, 0x89, 0xde, 0x31, 0x92, 0xe6, + 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, + 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, + 0x7c, + }; + + return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, out_buffer); +} + +CHIP_ERROR FactoryDataProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) +{ + out_firmware_info_buffer.reduce_size(0); + + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & outBuffer) +{ + ReturnErrorCodeIf(outBuffer.size() < mFactoryData.dac_cert.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.dac_cert.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(outBuffer.data(), mFactoryData.dac_cert.data, mFactoryData.dac_cert.len); + outBuffer.reduce_size(mFactoryData.dac_cert.len); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) +{ + ReturnErrorCodeIf(outBuffer.size() < mFactoryData.pai_cert.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.pai_cert.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(outBuffer.data(), mFactoryData.pai_cert.data, mFactoryData.pai_cert.len); + outBuffer.reduce_size(mFactoryData.pai_cert.len); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) +{ + Crypto::P256ECDSASignature signature; + Crypto::P256Keypair keypair; + + VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsSpanUsable(messageToSign), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); + + // Extract public key from DAC cert. + uint8_t dacBuf[600] = { 0 }; + MutableByteSpan dacCertSpan(dacBuf); + ReturnErrorCodeIf(dacCertSpan.size() < mFactoryData.dac_cert.len, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(dacCertSpan.data(), mFactoryData.dac_cert.data, mFactoryData.dac_cert.len); + dacCertSpan.reduce_size(mFactoryData.dac_cert.len); + chip::Crypto::P256PublicKey dacPublicKey; + + ReturnErrorOnFailure(chip::Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey)); + + uint8_t privKeyBuf[600] = { 0 }; + MutableByteSpan privKeySpan(privKeyBuf); + ReturnErrorCodeIf(privKeySpan.size() < mFactoryData.dac_priv_key.len, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(privKeySpan.data(), mFactoryData.dac_priv_key.data, mFactoryData.dac_priv_key.len); + privKeySpan.reduce_size(mFactoryData.dac_priv_key.len); + + uint8_t pubKeyBuf[600] = { 0 }; + MutableByteSpan pubKeySpan(pubKeyBuf); + ReturnErrorCodeIf(pubKeySpan.size() < dacPublicKey.Length(), CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(pubKeySpan.data(), dacPublicKey.Bytes(), dacPublicKey.Length()); + pubKeySpan.reduce_size(dacPublicKey.Length()); + + ReturnErrorOnFailure(LoadKeypairFromRaw(privKeySpan, pubKeySpan, keypair)); + ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); + + return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); +} +CHIP_ERROR FactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator) +{ + ReturnErrorCodeIf(sizeof(setupDiscriminator) < mFactoryData.discriminator.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.discriminator.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(&setupDiscriminator, mFactoryData.discriminator.data, mFactoryData.discriminator.len); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::SetSetupDiscriminator(uint16_t setupDiscriminator) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} +CHIP_ERROR FactoryDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount) +{ + ReturnErrorCodeIf(sizeof(iterationCount) < mFactoryData.spake2p_it.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.spake2p_it.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memset(&iterationCount, 0, sizeof(iterationCount)); + memcpy(&iterationCount, mFactoryData.spake2p_it.data, mFactoryData.spake2p_it.len); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf) +{ + ReturnErrorCodeIf(saltBuf.size() < mFactoryData.spake2p_salt.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.spake2p_salt.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(saltBuf.data(), mFactoryData.spake2p_salt.data, mFactoryData.spake2p_salt.len); + saltBuf.reduce_size(mFactoryData.spake2p_salt.len); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) +{ + ReturnErrorCodeIf(verifierBuf.size() < mFactoryData.spake2p_verifier.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.spake2p_verifier.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(verifierBuf.data(), mFactoryData.spake2p_verifier.data, mFactoryData.spake2p_verifier.len); + verifierLen = mFactoryData.spake2p_verifier.len; + verifierBuf.reduce_size(verifierLen); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetSetupPasscode(uint32_t & setupPasscode) +{ + ReturnErrorCodeIf(sizeof(setupPasscode) < mFactoryData.passcode.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.passcode.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(&setupPasscode, mFactoryData.passcode.data, mFactoryData.passcode.len); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::SetSetupPasscode(uint32_t setupPasscode) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} +CHIP_ERROR FactoryDataProvider::GetVendorName(char * buf, size_t bufSize) +{ + ReturnErrorCodeIf(bufSize < mFactoryData.vendor_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.vendor_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(buf, mFactoryData.vendor_name.data, mFactoryData.vendor_name.len); + buf[mFactoryData.vendor_name.len] = '\0'; + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetVendorId(uint16_t & vendorId) +{ + ReturnErrorCodeIf(sizeof(vendorId) < mFactoryData.vendor_id.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.vendor_id.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(&vendorId, mFactoryData.vendor_id.data, mFactoryData.vendor_id.len); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetProductName(char * buf, size_t bufSize) +{ + ReturnErrorCodeIf(bufSize < mFactoryData.product_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.product_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memset(buf, 0, bufSize); + memcpy(buf, mFactoryData.product_name.data, mFactoryData.product_name.len); + buf[mFactoryData.product_name.len] = '\0'; + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetProductId(uint16_t & productId) +{ + ReturnErrorCodeIf(sizeof(productId) < mFactoryData.product_id.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.product_id.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(&productId, mFactoryData.product_id.data, mFactoryData.product_id.len); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetPartNumber(char * buf, size_t bufSize) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} +CHIP_ERROR FactoryDataProvider::GetProductURL(char * buf, size_t bufSize) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} +CHIP_ERROR FactoryDataProvider::GetProductLabel(char * buf, size_t bufSize) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR FactoryDataProvider::GetSerialNumber(char * buf, size_t bufSize) +{ + ReturnErrorCodeIf(bufSize < mFactoryData.serial_number.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.serial_number.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memset(buf, 0, bufSize); + memcpy(buf, mFactoryData.serial_number.data, mFactoryData.serial_number.len); + buf[mFactoryData.serial_number.len] = '\0'; + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) +{ + ReturnErrorCodeIf(!mFactoryData.manufacturing_date.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + uint8_t tmp[10] = { 0 }; + memcpy(tmp, mFactoryData.manufacturing_date.data, 10); + year = ((tmp[0] - 0x30) * 1000) + ((tmp[1] - 0x30) * 100) + ((tmp[2] - 0x30) * 10) + (tmp[3] - 0x30); + month = ((tmp[5] - 0x30) * 10) + (tmp[6] - 0x30); + day = ((tmp[8] - 0x30) * 10) + (tmp[9] - 0x30); + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion) +{ + ReturnErrorCodeIf(sizeof(hardwareVersion) < mFactoryData.hw_ver.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.hw_ver.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(&hardwareVersion, mFactoryData.hw_ver.data, mFactoryData.hw_ver.len); + return CHIP_NO_ERROR; +} +CHIP_ERROR FactoryDataProvider::GetHardwareVersionString(char * buf, size_t bufSize) +{ + ReturnErrorCodeIf(bufSize < mFactoryData.hw_ver_str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.hw_ver_str.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memset(buf, 0, bufSize); + memcpy(buf, mFactoryData.hw_ver_str.data, mFactoryData.hw_ver_str.len); + buf[mFactoryData.hw_ver_str.len] = '\0'; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) +{ + ReturnErrorCodeIf(uniqueIdSpan.size() < mFactoryData.rd_uniqueid.len, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(!mFactoryData.rd_uniqueid.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); + memcpy(uniqueIdSpan.data(), mFactoryData.rd_uniqueid.data, mFactoryData.rd_uniqueid.len); + uniqueIdSpan.reduce_size(mFactoryData.rd_uniqueid.len); + + return CHIP_NO_ERROR; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13xx_26xx/FactoryDataProvider.h b/src/platform/cc13xx_26xx/FactoryDataProvider.h new file mode 100644 index 00000000000000..c84d28ac665915 --- /dev/null +++ b/src/platform/cc13xx_26xx/FactoryDataProvider.h @@ -0,0 +1,69 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +namespace chip { +namespace DeviceLayer { +class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentialsProvider, + public CommissionableDataProvider, + public DeviceInstanceInfoProvider +{ + +public: + static FactoryDataProvider & GetDefaultInstance(); + + FactoryDataProvider() {} + CHIP_ERROR Init(); + + // ===== Members functions that implement the DeviceAttestationCredentialsProvider + CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override; + CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override; + CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override; + CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override; + CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override; + + // ===== Members functions that implement the CommissionableDataProvider + CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; + CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override; + CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override; + CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override; + CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override; + CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override; + CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override; + + // ===== Members functions that implement the DeviceInstanceInfoProvider + CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override; + CHIP_ERROR GetVendorId(uint16_t & vendorId) override; + CHIP_ERROR GetProductName(char * buf, size_t bufSize) override; + CHIP_ERROR GetProductId(uint16_t & productId) override; + CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override; + CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override; + CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override; + CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override; + CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override; + CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override; + CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override; + CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override; +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn b/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn index ff746181a7f632..e0005c9fb2b9dd 100644 --- a/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn +++ b/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn @@ -16,6 +16,8 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/platform/device.gni") +import("../factory_data_config.gni") + assert(chip_device_platform == "cc13x2_26x2") if (chip_enable_openthread) { @@ -48,6 +50,12 @@ static_library("cc13x2_26x2") { deps = [ "${chip_root}/src/platform/logging:headers" ] + public = [ + "${chip_root}/src/credentials/CHIPCert.h", + "${chip_root}/src/credentials/CertificationDeclaration.h", + "${chip_root}/src/credentials/DeviceAttestationCredsProvider.h", + ] + public_deps = [ "${chip_root}/src/crypto", "${chip_root}/src/platform:platform_base", @@ -60,6 +68,12 @@ static_library("cc13x2_26x2") { ] } + if (custom_factory_data) { + sources += [ + "../FactoryDataProvider.cpp", + "../FactoryDataProvider.h", + ] + } if (chip_enable_ota_requestor) { sources += [ # this needs to be in the final link to place the data correctly diff --git a/src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos_ota_factory_data.lds b/src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos_ota_factory_data.lds new file mode 100644 index 00000000000000..3f0905e0a3135a --- /dev/null +++ b/src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos_ota_factory_data.lds @@ -0,0 +1,294 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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. + */ + +/** + * @file + * Linkerscript for Matter executable with space reserved for the TI BIM. + */ + +STACKSIZE = 0x800; +RESERVED_RAM_SIZE_BLE_ROM = 0x00000FDF; + + +MEMORY +{ + /* last two pages removed for BIM, Flash Bootloader, and Factory Data. CCFG is supplied by the BIM project */ + /* FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x000affa8 */ + /* FLASH_CCFG (RX) : ORIGIN = 0x000affa8, LENGTH = 0x00000058 */ + FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x000ac000 + FLASH_FACTORY_DATA (R) : ORIGIN = 0x000ac000, LENGTH = 0x00000900 + /* BLE ROM reserves RAM at the beginning of the ram image, size RESERVED_RAM_SIZE_BLE_ROM */ + /* SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00024000 */ + SRAM (RWX) : ORIGIN = 0x20000FDF, LENGTH = 0x00023021 + GPRAM (RWX) : ORIGIN = 0x11000000, LENGTH = 0x00002000 + /* Explicitly placed off target for the storage of logging data. + * The data placed here is NOT loaded onto the target device. + * This is part of 1 GB of external memory from 0x60000000 - 0x9FFFFFFF. + * ARM memory map can be found here: + * https://developer.arm.com/documentation/ddi0337/e/memory-map/about-the-memory-map + */ + LOG_DATA (R) : ORIGIN = 0x90000000, LENGTH = 0x40000 +} + +REGION_ALIAS("REGION_TEXT", FLASH); +REGION_ALIAS("REGION_FACTORY_DATA", FLASH_FACTORY_DATA); +REGION_ALIAS("REGION_BSS", SRAM); +REGION_ALIAS("REGION_DATA", SRAM); +REGION_ALIAS("REGION_STACK", SRAM); +REGION_ALIAS("REGION_HEAP", SRAM); +REGION_ALIAS("REGION_LOG", LOG_DATA); +REGION_ALIAS("REGION_ARM_EXIDX", FLASH); +REGION_ALIAS("REGION_ARM_EXTAB", FLASH); + +SECTIONS { + /* BIM header placed at the base of flash by default */ + PROVIDE (_img_header_base_address = + DEFINED(_img_header_base_address) ? _img_header_base_address : 0x0); + + .oad_image_header (_img_header_base_address) : AT (_img_header_base_address) { + KEEP (*(.oad_image_header)) + } > REGION_TEXT + + /* interrupt vectors shifted to accommodate BIM header */ + PROVIDE (_intvecs_base_address = + DEFINED(_intvecs_base_address) ? _intvecs_base_address : 0x100); + + .resetVecs (_intvecs_base_address) : AT (_intvecs_base_address) { + KEEP (*(.resetVecs)) + } > REGION_TEXT + + PROVIDE (_vtable_base_address = + DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000 + RESERVED_RAM_SIZE_BLE_ROM); + + .ramVecs (_vtable_base_address) (NOLOAD) : { + KEEP (*(.ramVecs)) + } > REGION_DATA + + /* Define base address for the DAC arrays and struct */ + PROVIDE (_factory_data_base_address = + DEFINED(_factory_data_base_address) ? _factory_data_base_address : 0xAC000); + + .factory_data(_factory_data_base_address) : AT (_factory_data_base_address) { + KEEP (*(.factory_data_struct)) + } > REGION_FACTORY_DATA + + /* + * UDMACC26XX_CONFIG_BASE below must match UDMACC26XX_CONFIG_BASE defined + * by ti/drivers/dma/UDMACC26XX.h + * The user is allowed to change UDMACC26XX_CONFIG_BASE to move it away from + * the default address 0x2000_1800, but remember it must be 1024 bytes aligned. + */ + UDMACC26XX_CONFIG_BASE = 0x20001800; + + /* + * Define absolute addresses for the DMA channels. + * DMA channels must always be allocated at a fixed offset from the DMA base address. + * --------- DO NOT MODIFY ----------- + */ + DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x10); + DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x20); + DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x30); + DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x40); + DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x50); + DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x60); + DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x70); + DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x90); + DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x100); + DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x110); + + DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x210); + DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x220); + DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x230); + DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x240); + DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x250); + DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x260); + DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x270); + DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x290); + DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x300); + DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x310); + + /* + * Allocate UART0, UART1, SPI0, SPI1, ADC, and GPTimer0 DMA descriptors at absolute addresses. + * --------- DO NOT MODIFY ----------- + */ + UDMACC26XX_uart0RxControlTableEntry_is_placed = 0; + .dmaUart0RxControlTableEntry DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0TxControlTableEntry_is_placed = 0; + .dmaUart0TxControlTableEntry DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0RxControlTableEntry_is_placed = 0; + .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0TxControlTableEntry_is_placed = 0; + .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1RxControlTableEntry_is_placed = 0; + .dmaUart1RxControlTableEntry DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1TxControlTableEntry_is_placed = 0; + .dmaUart1TxControlTableEntry DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaADCPriControlTableEntry_is_placed = 0; + .dmaADCPriControlTableEntry DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCPriControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaGPT0APriControlTableEntry_is_placed = 0; + .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0APriControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1RxControlTableEntry_is_placed = 0; + .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1TxControlTableEntry_is_placed = 0; + .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0RxAltControlTableEntry_is_placed = 0; + .dmaUart0RxAltControlTableEntry DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0TxAltControlTableEntry_is_placed = 0; + .dmaUart0TxAltControlTableEntry DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0RxAltControlTableEntry_is_placed = 0; + .dmaSpi0RxAltControlTableEntry DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0TxAltControlTableEntry_is_placed = 0; + .dmaSpi0TxAltControlTableEntry DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1RxAltControlTableEntry_is_placed = 0; + .dmaUart1RxAltControlTableEntry DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1TxAltControlTableEntry_is_placed = 0; + .dmaUart1TxAltControlTableEntry DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaADCAltControlTableEntry_is_placed = 0; + .dmaADCAltControlTableEntry DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaGPT0AAltControlTableEntry_is_placed = 0; + .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0AAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1RxAltControlTableEntry_is_placed = 0; + .dmaSpi1RxAltControlTableEntry DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1TxAltControlTableEntry_is_placed = 0; + .dmaSpi1TxAltControlTableEntry DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxAltControlTableEntry)} > REGION_DATA + + + + /* if a ROM-only symbol is present, then ROM is being used. + * Reserve memory for surgically placed config constants. + */ + _rom_rodata_start = 0x2000; + _rom_rodata_size = DEFINED(ROM_RODATA_SIZE) ? 0 : DEFINED(ROM_RODATA_SIZE_NO_OAD) ? 0x330 : 0; + + .rom_rodata_reserve (_rom_rodata_start): { + . += _rom_rodata_size; + } > REGION_TEXT AT> REGION_TEXT + + .text : { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + *(.init) + *(.fini*) + } > REGION_TEXT AT> REGION_TEXT + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : { + *(.rodata) + *(.rodata.*) + *(.rodata_*) + } > REGION_TEXT AT> REGION_TEXT + + .data : ALIGN(4) { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + *(.data) + *(.data.*) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + /* End of executable code/data, NVS is not part of the OTA image */ + PROVIDE (_flash_end_address = .); + + .nvs (0xA8000) (NOLOAD) : AT (0xA0000) ALIGN(0x2000) { + *(.nvs) + } > REGION_TEXT + + /* CCFG is supplied by the BIM project */ + /* + .ccfg : { + KEEP (*(.ccfg)) + } > FLASH_CCFG AT> FLASH_CCFG + */ + + .bss : { + __bss_start__ = .; + *(.shbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP(*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + __stack = .; + KEEP(*(.stack)) + . += STACKSIZE; + _stack_end = .; + __stack_end = .; + } > REGION_STACK AT> REGION_STACK + + .log_data (COPY) : { + KEEP (*(.log_data)) + } > REGION_LOG +} + +ENTRY(resetISR) diff --git a/src/platform/cc13xx_26xx/cc13x4_26x4/BUILD.gn b/src/platform/cc13xx_26xx/cc13x4_26x4/BUILD.gn index 414e7b1d78bcdc..0c62b3855ad353 100644 --- a/src/platform/cc13xx_26xx/cc13x4_26x4/BUILD.gn +++ b/src/platform/cc13xx_26xx/cc13x4_26x4/BUILD.gn @@ -16,6 +16,8 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/platform/device.gni") +import("../factory_data_config.gni") + assert(chip_device_platform == "cc13x4_26x4") if (chip_enable_openthread) { @@ -48,6 +50,12 @@ static_library("cc13x4_26x4") { deps = [ "${chip_root}/src/platform/logging:headers" ] + public = [ + "${chip_root}/src/credentials/CHIPCert.h", + "${chip_root}/src/credentials/CertificationDeclaration.h", + "${chip_root}/src/credentials/DeviceAttestationCredsProvider.h", + ] + public_deps = [ "${chip_root}/src/crypto", "${chip_root}/src/platform:platform_base", @@ -60,6 +68,13 @@ static_library("cc13x4_26x4") { ] } + if (custom_factory_data) { + sources += [ + "../FactoryDataProvider.cpp", + "../FactoryDataProvider.h", + ] + } + if (chip_enable_ota_requestor) { sources += [ "OTAImageProcessorImpl.cpp" ] } diff --git a/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos.lds b/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos.lds index 52e08615592fed..f639f640d2414d 100644 --- a/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos.lds +++ b/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos.lds @@ -256,4 +256,4 @@ SECTIONS { } > REGION_LOG } -ENTRY(resetISR) +ENTRY(resetISR) \ No newline at end of file diff --git a/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_factory_data.lds b/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_factory_data.lds new file mode 100644 index 00000000000000..c082497d88429e --- /dev/null +++ b/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_factory_data.lds @@ -0,0 +1,269 @@ +/* + * + * 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. + */ + +/** + * @file + * Linkerscript for a non-OTA Matter executable. + */ + +STACKSIZE = 0x2000; + +MEMORY +{ + FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x000FE800 + FLASH_FACTORY_DATA (R) : ORIGIN = 0x000FE800, LENGTH = 0x900 + /* + * Customer Configuration Area and Bootloader Backdoor configuration in + * flash + */ + FLASH_CCFG (RX) : ORIGIN = 0x50000000, LENGTH = 0x00000800 + SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00040000 + GPRAM (RWX) : ORIGIN = 0x11000000, LENGTH = 0x00002000 + /* Explicitly placed off target for the storage of logging data. + * The data placed here is NOT loaded onto the target device. + * This is part of 1 GB of external memory from 0x60000000 - 0x9FFFFFFF. + * ARM memory map can be found here: + * https://developer.arm.com/documentation/ddi0337/e/memory-map/about-the-memory-map + */ + LOG_DATA (R) : ORIGIN = 0x90000000, LENGTH = 0x40000 +} + +REGION_ALIAS("REGION_TEXT", FLASH); +REGION_ALIAS("REGION_FACTORY_DATA", FLASH_FACTORY_DATA); +REGION_ALIAS("REGION_BSS", SRAM); +REGION_ALIAS("REGION_DATA", SRAM); +REGION_ALIAS("REGION_STACK", SRAM); +REGION_ALIAS("REGION_HEAP", SRAM); +REGION_ALIAS("REGION_LOG", LOG_DATA); +REGION_ALIAS("REGION_ARM_EXIDX", FLASH); +REGION_ALIAS("REGION_ARM_EXTAB", FLASH); + +SECTIONS { + PROVIDE (_intvecs_base_address = + DEFINED(_intvecs_base_address) ? _intvecs_base_address : 0x00); + + .resetVecs (_intvecs_base_address) : AT (_intvecs_base_address) { + KEEP (*(.resetVecs)) + } > REGION_TEXT + + PROVIDE (_vtable_base_address = + DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000); + + .vtable (_vtable_base_address) (NOLOAD) : { + KEEP (*(.ramVecs)) + } > REGION_DATA + + /* Define base address for the DAC arrays and struct */ + PROVIDE (_factory_data_base_address = + DEFINED(_factory_data_base_address) ? _factory_data_base_address : 0xFE800); + + .factory_data(_factory_data_base_address) : AT (_factory_data_base_address) { + KEEP (*(.factory_data_struct)) + } > REGION_FACTORY_DATA + + /* + * UDMACC26XX_CONFIG_BASE below must match UDMACC26XX_CONFIG_BASE defined + * by ti/drivers/dma/UDMACC26XX.h + * The user is allowed to change UDMACC26XX_CONFIG_BASE to move it away from + * the default address 0x2000_0400, but remember it must be 1024 bytes aligned. + */ + UDMACC26XX_CONFIG_BASE = 0x20000400; + + /* + * Define absolute addresses for the DMA channels. + * DMA channels must always be allocated at a fixed offset from the DMA base address. + * --------- DO NOT MODIFY ----------- + */ + DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x10); + DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x20); + DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x30); + DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x40); + DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x50); + DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x60); + DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x70); + DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x90); + DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x100); + DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x110); + + DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x210); + DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x220); + DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x230); + DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x240); + DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x250); + DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x260); + DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x270); + DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x290); + DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x300); + DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x310); + + /* + * Allocate UART0, UART1, SPI0, SPI1, ADC, and GPTimer0 DMA descriptors at absolute addresses. + * --------- DO NOT MODIFY ----------- + */ + UDMACC26XX_uart0RxControlTableEntry_is_placed = 0; + .dmaUart0RxControlTableEntry DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0TxControlTableEntry_is_placed = 0; + .dmaUart0TxControlTableEntry DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0RxControlTableEntry_is_placed = 0; + .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0TxControlTableEntry_is_placed = 0; + .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1RxControlTableEntry_is_placed = 0; + .dmaUart1RxControlTableEntry DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1TxControlTableEntry_is_placed = 0; + .dmaUart1TxControlTableEntry DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaADCPriControlTableEntry_is_placed = 0; + .dmaADCPriControlTableEntry DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCPriControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaGPT0APriControlTableEntry_is_placed = 0; + .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0APriControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1RxControlTableEntry_is_placed = 0; + .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1TxControlTableEntry_is_placed = 0; + .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0RxAltControlTableEntry_is_placed = 0; + .dmaUart0RxAltControlTableEntry DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0TxAltControlTableEntry_is_placed = 0; + .dmaUart0TxAltControlTableEntry DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0RxAltControlTableEntry_is_placed = 0; + .dmaSpi0RxAltControlTableEntry DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0TxAltControlTableEntry_is_placed = 0; + .dmaSpi0TxAltControlTableEntry DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1RxAltControlTableEntry_is_placed = 0; + .dmaUart1RxAltControlTableEntry DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1TxAltControlTableEntry_is_placed = 0; + .dmaUart1TxAltControlTableEntry DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaADCAltControlTableEntry_is_placed = 0; + .dmaADCAltControlTableEntry DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaGPT0AAltControlTableEntry_is_placed = 0; + .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0AAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1RxAltControlTableEntry_is_placed = 0; + .dmaSpi1RxAltControlTableEntry DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1TxAltControlTableEntry_is_placed = 0; + .dmaSpi1TxAltControlTableEntry DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxAltControlTableEntry)} > REGION_DATA + + .text : { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + *(.init) + *(.fini*) + } > REGION_TEXT AT> REGION_TEXT + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : { + *(.rodata) + *(.rodata.*) + *(.rodata_*) + } > REGION_TEXT AT> REGION_TEXT + + .data : ALIGN(4) { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + *(.data) + *(.data.*) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + /* End of executable code/data, NVS is not part of the OTA image */ + PROVIDE (_flash_end_address = .); + + /* 5 pages of NV Memory (0x800 each) offset by 1 page for BIM/CCFG */ + /*.nvs (NOLOAD) : ALIGN(0x2000) { */ + .nvs (0xFB000) (NOLOAD) : AT (0xFB000) ALIGN(0x800) { + *(.nvs) + } > REGION_TEXT + + .ccfg : { + KEEP (*(.ccfg)) + } > FLASH_CCFG AT> FLASH_CCFG + + .bss : { + __bss_start__ = .; + *(.shbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP(*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + __stack = .; + KEEP(*(.stack)) + . += STACKSIZE; + _stack_end = .; + __stack_end = .; + } > REGION_STACK AT> REGION_STACK + + .log_data (COPY) : { + KEEP (*(.log_data)) + } > REGION_LOG +} + +ENTRY(resetISR) diff --git a/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_ota_factory_data.lds b/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_ota_factory_data.lds new file mode 100644 index 00000000000000..1228a3cc38d3e0 --- /dev/null +++ b/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_ota_factory_data.lds @@ -0,0 +1,280 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2020 Texas Instruments Incorporated + * + * 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. + */ + +/** + * @file + * Linkerscript for Matter executable with space reserved for MCUBoot. + */ + +STACKSIZE = 0x2000; + +MEMORY +{ + MCUBOOT_HDR (RX) : ORIGIN = 0x00006000, LENGTH = 0x00000080 + FLASH (RX) : ORIGIN = 0x00006080, LENGTH = 0x000F8780 + /* + * NVS is the last 5 pages of slot, this area is not erased + * during OTA. The slot size for the primary and secondary slots + * is therefore 0xF6000 (MCUBoot Header + all the remaining space) + */ + /* FLASH_NVS (RX) : ORIGIN = 0x000FC000, LENGTH = 0x00002800 */ + FLASH_FACTORY_DATA (R) : ORIGIN = 0x000FE800, LENGTH = 0x900 + /* + * Customer Configuration Area and Bootloader Backdoor configuration in + * flash + */ + /* FLASH_CCFG (RX) : ORIGIN = 0x50000000, LENGTH = 0x00000800 */ + SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00040000 + GPRAM (RWX) : ORIGIN = 0x11000000, LENGTH = 0x00002000 + /* Explicitly placed off target for the storage of logging data. + * The data placed here is NOT loaded onto the target device. + * This is part of 1 GB of external memory from 0x60000000 - 0x9FFFFFFF. + * ARM memory map can be found here: + * https://developer.arm.com/documentation/ddi0337/e/memory-map/about-the-memory-map + */ + LOG_DATA (R) : ORIGIN = 0x90000000, LENGTH = 0x40000 +} + +REGION_ALIAS("REGION_TEXT", FLASH); +REGION_ALIAS("REGION_FACTORY_DATA", FLASH_FACTORY_DATA); +REGION_ALIAS("REGION_BSS", SRAM); +REGION_ALIAS("REGION_DATA", SRAM); +REGION_ALIAS("REGION_STACK", SRAM); +REGION_ALIAS("REGION_HEAP", SRAM); +REGION_ALIAS("REGION_LOG", LOG_DATA); +REGION_ALIAS("REGION_ARM_EXIDX", FLASH); +REGION_ALIAS("REGION_ARM_EXTAB", FLASH); + +SECTIONS { + /* interrupt vectors shifted to accommodate MCUBoot header */ + PROVIDE (_intvecs_base_address = + DEFINED(_intvecs_base_address) ? _intvecs_base_address : 0x6080); + + .resetVecs (_intvecs_base_address) : AT (_intvecs_base_address) { + KEEP (*(.resetVecs)) + } > REGION_TEXT + + PROVIDE (_vtable_base_address = + DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000); + + .vtable (_vtable_base_address) (NOLOAD) : { + KEEP (*(.ramVecs)) + } > REGION_DATA + + /* Define base address for the Factory Data arrays and struct */ + PROVIDE (_factory_data_base_address = + DEFINED(_factory_data_base_address) ? _factory_data_base_address : 0xFE800); + + .factory_data(_factory_data_base_address) : AT (_factory_data_base_address) { + KEEP (*(.factory_data_struct)) + } > REGION_FACTORY_DATA + + /* + * UDMACC26XX_CONFIG_BASE below must match UDMACC26XX_CONFIG_BASE defined + * by ti/drivers/dma/UDMACC26XX.h + * The user is allowed to change UDMACC26XX_CONFIG_BASE to move it away from + * the default address 0x2000_0400, but remember it must be 1024 bytes aligned. + */ + UDMACC26XX_CONFIG_BASE = 0x20000400; + + /* + * Define absolute addresses for the DMA channels. + * DMA channels must always be allocated at a fixed offset from the DMA base address. + * --------- DO NOT MODIFY ----------- + */ + DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x10); + DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x20); + DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x30); + DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x40); + DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x50); + DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x60); + DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x70); + DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x90); + DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x100); + DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x110); + + DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x210); + DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x220); + DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x230); + DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x240); + DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x250); + DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x260); + DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x270); + DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x290); + DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x300); + DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x310); + + /* + * Allocate UART0, UART1, SPI0, SPI1, ADC, and GPTimer0 DMA descriptors at absolute addresses. + * --------- DO NOT MODIFY ----------- + */ + UDMACC26XX_uart0RxControlTableEntry_is_placed = 0; + .dmaUart0RxControlTableEntry DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0TxControlTableEntry_is_placed = 0; + .dmaUart0TxControlTableEntry DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0RxControlTableEntry_is_placed = 0; + .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0TxControlTableEntry_is_placed = 0; + .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1RxControlTableEntry_is_placed = 0; + .dmaUart1RxControlTableEntry DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1TxControlTableEntry_is_placed = 0; + .dmaUart1TxControlTableEntry DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaADCPriControlTableEntry_is_placed = 0; + .dmaADCPriControlTableEntry DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCPriControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaGPT0APriControlTableEntry_is_placed = 0; + .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0APriControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1RxControlTableEntry_is_placed = 0; + .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1TxControlTableEntry_is_placed = 0; + .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0RxAltControlTableEntry_is_placed = 0; + .dmaUart0RxAltControlTableEntry DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart0TxAltControlTableEntry_is_placed = 0; + .dmaUart0TxAltControlTableEntry DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0RxAltControlTableEntry_is_placed = 0; + .dmaSpi0RxAltControlTableEntry DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi0TxAltControlTableEntry_is_placed = 0; + .dmaSpi0TxAltControlTableEntry DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1RxAltControlTableEntry_is_placed = 0; + .dmaUart1RxAltControlTableEntry DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_uart1TxAltControlTableEntry_is_placed = 0; + .dmaUart1TxAltControlTableEntry DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaADCAltControlTableEntry_is_placed = 0; + .dmaADCAltControlTableEntry DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaGPT0AAltControlTableEntry_is_placed = 0; + .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0AAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1RxAltControlTableEntry_is_placed = 0; + .dmaSpi1RxAltControlTableEntry DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxAltControlTableEntry)} > REGION_DATA + + UDMACC26XX_dmaSpi1TxAltControlTableEntry_is_placed = 0; + .dmaSpi1TxAltControlTableEntry DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxAltControlTableEntry)} > REGION_DATA + + .text : { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + *(.init) + *(.fini*) + } > REGION_TEXT AT> REGION_TEXT + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : { + *(.rodata) + *(.rodata.*) + *(.rodata_*) + } > REGION_TEXT AT> REGION_TEXT + + .data : ALIGN(4) { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + *(.data) + *(.data.*) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + /* End of executable code/data, NVS is not part of the OTA image */ + PROVIDE (_flash_end_address = .); + + /* 5 pages of NV Memory (0x800 each) at the end of Flash */ + .nvs (0xFC000) (NOLOAD) : AT (0xFC000) ALIGN(0x800) { + *(.nvs) + } > REGION_TEXT + + /* CCFG is supplied by the MCUBoot project */ + /* + .ccfg : { + KEEP (*(.ccfg)) + } > FLASH_CCFG AT> FLASH_CCFG + */ + + .bss (NOLOAD) : { + __bss_start__ = .; + *(.shbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap (NOLOAD) : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP(*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + __stack = .; + KEEP(*(.stack)) + . += STACKSIZE; + _stack_end = .; + __stack_end = .; + } > REGION_STACK AT> REGION_STACK + + .log_data (COPY) : { + KEEP (*(.log_data)) + } > REGION_LOG +} + +ENTRY(resetISR) diff --git a/src/platform/cc13xx_26xx/factory_data.schema b/src/platform/cc13xx_26xx/factory_data.schema new file mode 100644 index 00000000000000..62331d3fa47a25 --- /dev/null +++ b/src/platform/cc13xx_26xx/factory_data.schema @@ -0,0 +1,100 @@ +{ + "$id": "TI_Factory_Data_schema", + "$schema": "https://example.com/employee.schema.json", + "description": "A representation of all factory data used in TI Matter devices", + "type": "object", + "properties": { + "elements": { + "type": "array", + "items":{ + "description":"Factory data elements", + "type": "object", + "properties": { + "serial_number": { + "description": "Serial number of device", + "type": "string", + "maxLength": 32 + }, + "vendor_id": { + "description": "Vendor Identifier", + "type": "integer", + "minimum": 0, + "maximum": 65524 + }, + "product_id": { + "description": "Product Identifier", + "type": "integer", + "minimum": 1, + "maximum": 65535 + }, + "vendor_name": { + "description": "human-readable vendor name", + "type": "string", + "maxLength": 32 + }, + "product_name": { + "description": "human-readable product name", + "type": "string", + "maxLength": 32 + }, + "manufacturing_date": { + "description": "Manufacturing date according to ISO 8601 in notation YYYY-MM-DD", + "type": "string", + "format": "date", + "minLength": 10, + "maxLength": 10, + "pattern": "^\\d{4}-\\d{2}-\\d{2}$" + }, + "hw_ver": { + "description": "Hardware version - integer", + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "hw_ver_str": { + "description": "A string representation of hardware version", + "type": "string", + "minLength": 1, + "maxLength": 64 + }, + "rd_uid": { + "description": "A randomly-generated 128-bit or longer octet string. Length has been expanded with 'hex:' prefix", + "type": "string", + "pattern": "^hex:([0-9A-Fa-f]{2}){16,}$", + "minLength": 36, + "maxLength": 68 + }, + "dac_cert": { + "description": "DAC certificate string", + "type": "string" + }, + "dac_priv_key": { + "description": "DAC private key string", + "type": "string" + }, + "pai_cert": { + "description": "PAI certificate string", + "type": "string" + }, + "spake2_it": { + "description": "An Iteration counter for the Symmetric Password-Authenticated Key Exchange", + "type": "integer", + "minimum": 1000, + "maximum": 100000 + }, + "spake2_salt": { + "description": "A key-derivation function for the Symmetric Password-Authenticated Key Exchange.", + "type": "string", + "pattern": "^hex:([0-9A-Fa-f]{2}){16,}$" + }, + "spake2_verifier": { + "description": "A verifier for the Symmetric Password-Authenticated Key Exchange", + "type": "string", + "pattern": "^hex:([0-9A-Fa-f]{2}){16,}$" + } + } + } + } + } +} + diff --git a/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json b/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json new file mode 100644 index 00000000000000..1dc884cc5a23b6 --- /dev/null +++ b/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json @@ -0,0 +1,72 @@ +{ + "elements": [ + { + "serial_number": "1234567890", + "len": 10 + }, + { + "vendor_id": 65521, + "len": 2 + }, + { + "product_id": 32778, + "len": 2 + }, + { + "vendor_name": "Texas Instruments", + "len": 17 + }, + { + "product_name": "PumpApp", + "len": 7 + }, + { + "manufacturing_date": "2023-07-05", + "len": 10 + }, + { + "hw_ver": 1234, + "len": 2 + }, + { + "hw_ver_str": "1234", + "len": 4 + }, + { + "dac_cert": "hex:308201f73082019da00302010202084688eb94ad32b2e4300a06082a8648ce3d040302304d311f301d06035504030c164d617474657220446576656c6f706d656e742050414931143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030363020170d3231303632383134323334335a180f39393939313233313233353935395a30523124302206035504030c1b4d617474657220446576656c6f706d656e7420444143203030303031143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030363059301306072a8648ce3d020106082a8648ce3d03010703420004c565fdadfd16dd62e43f1960b993bb572cfdd81f6d7167671b7745dcbe6f65af665a1d931c05b9f9a3e9456685602c05c69646b8f75998dbaa687a5c564902daa360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604149b40606f9e047fb860788e3dc112d75e87957768301f0603551d2304183016801443345712ba2c87ef25497b11d798589b84357f88300a06082a8648ce3d0403020348003045022100b928f93ee387ef3e0072882284bd8add5cd6d05581bfcc5517cf9e9bcdd437da022010079ccf7f1f2dda46ace967ae5be966e7f28adfa028b8f87f939ed4158dc0f8", + "len": 507 + }, + { + "dac_priv_key": "hex:505a211dbda871330d635da3b07eb1c5088a8fc70124fbb33e93d5060582c7c5", + "len": 32 + }, + { + "pai_cert": "hex:308201dc30820181a00302010202087f7ef3db08a38f68300a06082a8648ce3d04030230303118301606035504030c0f4d617474657220546573742050414131143012060a2b0601040182a27c02010c04464646313020170d3231303632383134323334335a180f39393939313233313233353935395a304d311f301d06035504030c164d617474657220446576656c6f706d656e742050414931143012060a2b0601040182a27c02010c044646463131143012060a2b0601040182a27c02020c04383030363059301306072a8648ce3d020106082a8648ce3d0301070342000442935577353515cefa8f0e30e2347e90eed6fd515be882d1bcba7483d7ff6ef4dedf98f7f74f17421de5450cfffb3e7f6d4f6228534114fbb85c2d52d182b66aa366306430120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020106301d0603551d0e0416041443345712ba2c87ef25497b11d798589b84357f88301f0603551d230418301680146afd22771f511fecbf1641976710dcdc31a1717e300a06082a8648ce3d0403020349003046022100ff25f1d154c3137e0e086d82ab0b11b5661839b712b1342c6cde94fbe318a92b02210092e281f98a2fcc14cdf40750d280d7dfea3f4da46f357afeacb89b267706d28a", + "len": 480 + }, + { + "rd_uniqueid": "hex:91a9c12a7c80700a31ddcfa7fce63e44", + "len": 16 + }, + { + "spake2_it": 2000, + "len": 2 + }, + { + "spake2_salt": "hex:5350414b453250204b65792053616c74", + "len": 16 + }, + { + "spake2_verifier": "hex:7d04776bb469c494922830144f3fa2f19cfd82c04d108d8ba6353fdd92c01f9304511b6c4765bab147949dd942c43b3d8dc6323089ca3189d9e4a5636e16d82f1aef728b0d902c1a9b0f7e9652ab7f657861b6bbacd6bfdf04f80709248b83dec7", + "len": 97 + }, + { + "discriminator": 3840, + "len": 2 + }, + { + "passcode": 20202021, + "len": 4 + } + ] +} diff --git a/src/platform/cc13xx_26xx/factory_data_config.gni b/src/platform/cc13xx_26xx/factory_data_config.gni new file mode 100644 index 00000000000000..4f5a1b319256cf --- /dev/null +++ b/src/platform/cc13xx_26xx/factory_data_config.gni @@ -0,0 +1,17 @@ +# 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. + +declare_args() { + custom_factory_data = "" +} diff --git a/third_party/ti_simplelink_sdk/create_factory_data.py b/third_party/ti_simplelink_sdk/create_factory_data.py new file mode 100644 index 00000000000000..224979a9587306 --- /dev/null +++ b/third_party/ti_simplelink_sdk/create_factory_data.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python + +# 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. + +import argparse +import json +import subprocess + +import intelhex +from jsonschema import validate + + +def create_hex_file(args): + # create empty factory data file + factory_data_intelhex = intelhex.IntelHex() + factory_data_struct_intelhex = intelhex.IntelHex() + + device_family = args.device_family + + # there are 17 elements, each element will need 8 bytes in the struct + # 4 for length of the element, and 4 for the pointer to the element + # factory data starts at 0xAC000 or 0xFE800, so the elements will + # start 136 bytes after the start address + factory_data_dict = json.load(args.factory_data_json_file[0]) + factory_data_schema = json.load(args.factory_data_schema[0]) + + validate(factory_data_dict, factory_data_schema) + factory_data = factory_data_dict['elements'] + + struct_idx = 0 + values_idx = 0 + if device_family == 'cc13x2_26x2': + value_address = 0xAC088 + else: + value_address = 0xFE888 + + for element in factory_data: + # get the length in hex and write to first hex file + len_integer = element['len'] + + factory_data_struct_intelhex[struct_idx + 3] = (len_integer & 0xFF000000) >> 24 + factory_data_struct_intelhex[struct_idx + 2] = (len_integer & 0x00FF0000) >> 16 + factory_data_struct_intelhex[struct_idx + 1] = (len_integer & 0x0000FF00) >> 8 + factory_data_struct_intelhex[struct_idx] = (len_integer & 0x000000FF) + + struct_idx += 4 + + # write the address to the file and increment by the size of the element + factory_data_struct_intelhex[struct_idx + 3] = (value_address & 0xFF000000) >> 24 + factory_data_struct_intelhex[struct_idx + 2] = (value_address & 0x00FF0000) >> 16 + factory_data_struct_intelhex[struct_idx + 1] = (value_address & 0x0000FF00) >> 8 + factory_data_struct_intelhex[struct_idx] = (value_address & 0x000000FF) + + struct_idx += 4 + value_address += len_integer + + # convert the value to hex and write to the second file + key = list(element.keys())[0] + if type(element[key]) == str: + list_value = list(element[key].strip(" ")) + hex_check = ''.join(list_value[0:4]) + if hex_check == "hex:": + list_value = list_value[4:] + idx = 0 + list_len = len(list_value) + while idx < list_len: + hex_list = [] + hex_str_1 = list_value[idx] + + hex_list.append(hex_str_1) + hex_str_2 = list_value[idx+1] + + hex_list.append(hex_str_2) + final_hex_str = ''.join(hex_list) + + factory_data_intelhex[values_idx] = int(final_hex_str, 16) + values_idx += 1 + idx += 2 + else: + for ele in list_value: + factory_data_intelhex[values_idx] = ord(ele) + values_idx += 1 + else: + if key != "spake2_it" and key != "passcode": + factory_data_intelhex[values_idx] = (element[key] & 0x00FF) + factory_data_intelhex[values_idx + 1] = (element[key] & 0xFF00) >> 8 + + values_idx += 2 + elif key == "spake2_it": + if len_integer == 2: + factory_data_intelhex[values_idx] = (element[key] & 0x00FF) + factory_data_intelhex[values_idx + 1] = (element[key] & 0xFF00) >> 8 + + values_idx += 2 + elif len_integer == 3: + factory_data_intelhex[values_idx] = (element[key] & 0x0000FF) + factory_data_intelhex[values_idx + 1] = (element[key] & 0x00FF00) >> 8 + factory_data_intelhex[values_idx + 2] = (element[key] & 0xFF0000) >> 16 + + values_idx += 3 + else: + factory_data_intelhex[values_idx] = (element[key] & 0x000000FF) + factory_data_intelhex[values_idx + 1] = (element[key] & 0x0000FF00) >> 8 + factory_data_intelhex[values_idx + 2] = (element[key] & 0x00FF0000) >> 16 + factory_data_intelhex[values_idx + 3] = (element[key] & 0xFF000000) >> 24 + + values_idx += 4 + else: + factory_data_intelhex[values_idx] = (element[key] & 0x000000FF) + factory_data_intelhex[values_idx + 1] = (element[key] & 0x0000FF00) >> 8 + factory_data_intelhex[values_idx + 2] = (element[key] & 0x00FF0000) >> 16 + factory_data_intelhex[values_idx + 3] = (element[key] & 0xFF000000) >> 24 + + values_idx += 4 + + # merge both hex files + idx = 0 + while idx < values_idx: + factory_data_struct_intelhex[struct_idx] = factory_data_intelhex[idx] + idx = idx + 1 + struct_idx = struct_idx + 1 + + # output to hex file + factory_data_struct_intelhex.tofile(args.factory_data_hex_file, format='hex') + + # get hex file in a format that can be merged in a later step + subprocess.call(['objcopy', args.factory_data_hex_file, '--input-target', 'ihex', '--output-target', 'binary', 'temp.bin']) + if device_family == 'cc13x2_26x2': + subprocess.call(['objcopy', 'temp.bin', '--input-target', 'binary', '--output-target', + 'ihex', args.factory_data_hex_file, '--change-addresses=0xac000']) + else: + subprocess.call(['objcopy', 'temp.bin', '--input-target', 'binary', '--output-target', + 'ihex', args.factory_data_hex_file, '--change-addresses=0xfe800']) + subprocess.call(['rm', 'temp.bin']) + + +def main(): + parser = argparse.ArgumentParser(description="TI Factory Data hex file creator") + + parser.add_argument('-factory_data', '--factory_data_json_file', required=True, nargs=1, + help="JSON file of factory data", type=argparse.FileType('r')) + parser.add_argument('-schema', '--factory_data_schema', required=True, nargs=1, + help="Factory Data Schema", type=argparse.FileType('r')) + parser.add_argument('-o', '--factory_data_hex_file', required=True) + parser.add_argument('-device', '--device_family', required=True) + + args = parser.parse_args() + create_hex_file(args) + + +if __name__ == "__main__": + main() diff --git a/third_party/ti_simplelink_sdk/factory_data_merge_tool.py b/third_party/ti_simplelink_sdk/factory_data_merge_tool.py new file mode 100644 index 00000000000000..af475737a8b254 --- /dev/null +++ b/third_party/ti_simplelink_sdk/factory_data_merge_tool.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +# 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. + +"""Simple hexmerge script for combining the BIM, Factory Data, and App + +This script provides a basic utility to combine the Matter application hex file and Factory Data hex file. The output is a combined hex file that can be programmed on the target and run. + +Run with: + python factory_data_merge_tool.py +""" + +import sys + +import intelhex + +hex_file = sys.argv[1] +factory_data = sys.argv[2] +combined_hex = sys.argv[3] + +# merge matter hex file and factory hex file +matter_hex = intelhex.IntelHex() +matter_hex.fromfile(hex_file, format='hex') + +factory_data_hex = intelhex.IntelHex() +factory_data_hex.fromfile(factory_data, format='hex') + +matter_hex.merge(factory_data_hex, overlap='replace') +matter_hex.tofile(combined_hex, format='hex') diff --git a/third_party/ti_simplelink_sdk/factory_data_trim.py b/third_party/ti_simplelink_sdk/factory_data_trim.py new file mode 100644 index 00000000000000..c38be1f0a0a2ac --- /dev/null +++ b/third_party/ti_simplelink_sdk/factory_data_trim.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +# 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. + +"""Script to extract the factory data content from the matter application + factory data image + +This script will trim the factory data content out of the matter application image. It will also get the length of the factory data from the matter application map file. The output is the Matter image without the dummy factory d. + +Run with: + python factory_data_trim.py +""" + +import itertools +import re +import sys + +import intelhex + +matter_app_file = sys.argv[1] +matter_app_map_file = sys.argv[2] +matter_image_without_factory_data_hex = sys.argv[3] +device_family = sys.argv[4] + +# extract factory data length from map file +with open(matter_app_map_file, "r") as map_file: + if device_family == 'cc13x2_26x2': + pattern = ".factory_data 0x000ac000" + else: + pattern = ".factory_data 0x000fe800" + for line in map_file: + if re.search(pattern, line): + factory_data_num_bytes = line + break + +# this is the length of the factory data in hexadecmial form +factory_data_num_bytes = factory_data_num_bytes[32:] + +# convert hex image to dictionary +matter_image = intelhex.IntelHex() +matter_image.fromfile(matter_app_file, format='hex') +matter_image_dict = matter_image.todict() + +if device_family == 'cc13x2_26x2': + # 704512 is 0xAC000 - start of factory data + start_index = list(matter_image_dict.keys()).index(704512) +else: + # 1042432 is 0xFE800 - start of factory data + start_index = list(matter_image_dict.keys()).index(1042432) +# convert length of factory data into a decimal value +end_index = start_index + int(factory_data_num_bytes, 16) + +# slice dictionary to remove factory data elements +matter_image_dict_first_half = dict(itertools.islice(matter_image_dict.items(), 0, start_index)) +matter_image_dict_second_half = dict(itertools.islice(matter_image_dict.items(), end_index, len(matter_image_dict))) + +# convert sliced dictionary to back to hex +matter_image_without_factory_data_first_half = intelhex.IntelHex() +matter_image_without_factory_data_second_half = intelhex.IntelHex() + +matter_image_without_factory_data_first_half.fromdict(matter_image_dict_first_half) +matter_image_without_factory_data_second_half.fromdict(matter_image_dict_second_half) + +matter_image_without_factory_data_first_half.merge(matter_image_without_factory_data_second_half, overlap='error') + +matter_image_without_factory_data_first_half.tofile(matter_image_without_factory_data_hex, format='hex') diff --git a/third_party/ti_simplelink_sdk/oad_and_factory_data_merge_tool.py b/third_party/ti_simplelink_sdk/oad_and_factory_data_merge_tool.py new file mode 100644 index 00000000000000..d98fc94593dd95 --- /dev/null +++ b/third_party/ti_simplelink_sdk/oad_and_factory_data_merge_tool.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +# 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. + +"""Simple hexmerge script for combining the BIM, Factory Data, and App + +This script provides a basic utility to combine the OAD application binary file with the Boot Image Manager hex file and Factory Data hex file. The output is a combined hex file that can be programmed on the target and run. + +Run with: + python oad_and_factory_data_merge_tool.py +""" + +import sys + +import intelhex + +oad_bin_file = sys.argv[1] +bim_hex_file = sys.argv[2] +factory_data = sys.argv[3] +combined_hex = sys.argv[4] + +# merge binary executable with bim hex file and factory hex file +ota_image = intelhex.IntelHex() +if (oad_bin_file.endswith('hex')): + ota_image.fromfile(oad_bin_file, format='hex') + +else: + ota_image.fromfile(oad_bin_file, format='bin') + +bim_hex = intelhex.IntelHex() +bim_hex.fromfile(bim_hex_file, format='hex') + +factory_data_hex = intelhex.IntelHex() +factory_data_hex.fromfile(factory_data, format='hex') + +ota_image.merge(bim_hex, overlap='error') +ota_image.merge(factory_data_hex, overlap='replace') + +ota_image.tofile(combined_hex, format='hex') diff --git a/third_party/ti_simplelink_sdk/ti_simplelink_executable.gni b/third_party/ti_simplelink_sdk/ti_simplelink_executable.gni index 9cc800e9b1e139..1da4bbb0e76763 100644 --- a/third_party/ti_simplelink_sdk/ti_simplelink_executable.gni +++ b/third_party/ti_simplelink_sdk/ti_simplelink_executable.gni @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/ti_simplelink_sdk.gni") import("${build_root}/toolchain/flashable_executable.gni") +import("${chip_root}/src/platform/cc13xx_26xx/factory_data_config.gni") import("${chip_root}/src/platform/device.gni") import("ti_simplelink_board.gni") import("ti_simplelink_sdk.gni") @@ -75,7 +76,11 @@ template("ti_simplelink_executable") { if (chip_enable_ota_requestor) { sources += [ "${chip_root}/src/platform/cc13xx_26xx/oad_image_header.c" ] - ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos_ota.lds" + if (custom_factory_data) { + ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos_ota_factory_data.lds" + } else { + ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos_ota.lds" + } } else { ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x2_26x2/cc13x2x7_cc26x2x7_freertos.lds" } @@ -83,9 +88,17 @@ template("ti_simplelink_executable") { if (chip_enable_ota_requestor) { sources += [ "${chip_root}/src/platform/cc13xx_26xx/oad_image_header.c" ] - ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_ota.lds" + if (custom_factory_data) { + ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_ota_factory_data.lds" + } else { + ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_ota.lds" + } } else { - ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos.lds" + if (custom_factory_data) { + ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos_factory_data.lds" + } else { + ldscript = "${chip_root}/src/platform/cc13xx_26xx/cc13x4_26x4/cc13x4_cc26x4_freertos.lds" + } } } else if (ti_simplelink_device_family == "cc32xx") { ldscript = "${ti_simplelink_sdk_root}/source/ti/boards/cc32xxsf/cc32xxsf_freertos.lds" @@ -104,11 +117,67 @@ template("ti_simplelink_executable") { if (chip_enable_ota_requestor) { if (ti_simplelink_device_family == "cc13x2x7_26x2x7") { + if (custom_factory_data) { + pw_python_action("${simplelink_target_name}-without-factory-data.hex") { + public_deps = [ ":${simplelink_target_name}.out.image" ] + + script = "${ti_simplelink_sdk_build_root}/factory_data_trim.py" + sources = [ "${root_out_dir}/${objcopy_image_name}" ] + outputs = + [ "${root_out_dir}/${output_base_name}-without-factory-data.hex" ] + + args = [ + rebase_path("${root_out_dir}/${output_base_name}.hex", + root_out_dir), + rebase_path("${root_out_dir}/${output_base_name}.out.map", + root_out_dir), + rebase_path( + "${root_out_dir}/${output_base_name}-without-factory-data.hex", + root_out_dir), + "cc13x2_26x2", + ] + } + pw_python_action("${simplelink_target_name}-factory-data.hex") { + script = "${ti_simplelink_sdk_build_root}/create_factory_data.py" + sources = [ + "${chip_root}/src/platform/cc13xx_26xx/factory_data.schema", + "${chip_root}/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json", + ] + outputs = [ "${root_out_dir}/${output_base_name}-factory-data.hex" ] + + args = [ + "-factory_data", + rebase_path( + "${chip_root}/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json"), + "-schema", + rebase_path( + "${chip_root}/src/platform/cc13xx_26xx/factory_data.schema"), + "-o", + rebase_path("${root_out_dir}/${output_base_name}-factory-data.hex", + root_out_dir), + "-device", + "cc13x2_26x2", + ] + } + } pw_python_action("${simplelink_target_name}.bin") { - public_deps = [ ":${simplelink_target_name}.out.image" ] + if (custom_factory_data) { + public_deps = + [ ":${simplelink_target_name}-without-factory-data.hex" ] + } else { + public_deps = [ ":${simplelink_target_name}.out.image" ] + } script = "${ti_simplelink_sdk_root}//tools/common/oad/oad_image_tool.py" - sources = [ "${root_out_dir}/${objcopy_image_name}" ] + if (custom_factory_data) { + sources = + [ "${root_out_dir}/${output_base_name}-without-factory-data.hex" ] + input_path = + "${root_out_dir}/${output_base_name}-without-factory-data.hex" + } else { + sources = [ "${root_out_dir}/${objcopy_image_name}" ] + input_path = "${root_out_dir}/${output_base_name}.hex" + } outputs = [ "${root_out_dir}/${output_base_name}.bin" ] args = [ @@ -117,7 +186,7 @@ template("ti_simplelink_executable") { rebase_path(root_out_dir, root_build_dir), "7", "-hex1", - rebase_path("${root_out_dir}/${output_base_name}.hex", root_out_dir), + rebase_path(input_path, root_out_dir), "-o", output_base_name, ] @@ -136,12 +205,22 @@ template("ti_simplelink_executable") { ] } } - action("${simplelink_target_name}-bim.hex") { + pw_python_action("${simplelink_target_name}-bim.hex") { public_deps = [ ":${simplelink_target_name}.bin" ] + if (custom_factory_data) { + public_deps += [ ":${simplelink_target_name}-factory-data.hex" ] - script = "${ti_simplelink_sdk_build_root}/oad_merge_tool.py" - sources = [ "${root_out_dir}/${output_base_name}.bin" ] - outputs = [ "${root_out_dir}/${output_base_name}-bim.hex" ] + script = "${ti_simplelink_sdk_build_root}/oad_and_factory_data_merge_tool.py" + sources = [ + "${root_out_dir}/${output_base_name}-factory-data.hex", + "${root_out_dir}/${output_base_name}.bin", + ] + outputs = [ "${root_out_dir}/${output_base_name}-bim.hex" ] + } else { + script = "${ti_simplelink_sdk_build_root}/oad_merge_tool.py" + sources = [ "${root_out_dir}/${output_base_name}.bin" ] + outputs = [ "${root_out_dir}/${output_base_name}-bim.hex" ] + } if (defined(invoker.bim_hex)) { bim_hex = invoker.bim_hex @@ -149,16 +228,30 @@ template("ti_simplelink_executable") { bim_hex = "${ti_simplelink_sdk_root}/examples/nortos/${ti_simplelink_board}/bim/hexfiles/bim_offchip/Release/bim_offchip.hex" } - args = [ - rebase_path("${root_out_dir}/${output_base_name}.bin", - root_build_dir), - rebase_path(bim_hex, root_build_dir), - rebase_path("${root_out_dir}/${output_base_name}-bim.hex", - root_build_dir), - ] + if (custom_factory_data) { + args = [ + rebase_path("${root_out_dir}/${output_base_name}.bin", + root_build_dir), + rebase_path(bim_hex, root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-factory-data.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-bim.hex", + root_build_dir), + ] + } else { + args = [ + rebase_path("${root_out_dir}/${output_base_name}.bin", + root_build_dir), + rebase_path(bim_hex, root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-bim.hex", + root_build_dir), + ] + } + + args += [ "${root_out_dir}/${output_base_name}-bim.hex" ] } pw_python_action("${target_name}.ota") { - public_deps = [ ":${simplelink_target_name}.bin" ] + public_deps = [ ":${simplelink_target_name}-bim.hex" ] script = "${chip_root}/src/app/ota_image_tool.py" sources = [ "${root_out_dir}/${output_base_name}.bin" ] @@ -187,23 +280,97 @@ template("ti_simplelink_executable") { "-da", matter_ota_digest, ] - } else { + args += [ - "-da", - "sha256", + "-v", + matter_device_vid, + "-p", + matter_device_pid, + "-vn", + matter_software_ver, + "-vs", + matter_software_ver_str, ] - } - if (defined(invoker.ota_args)) { - args += invoker.ota_args + if (defined(invoker.ota_digest)) { + args += [ + "-da", + matter_ota_digest, + ] + } else { + args += [ + "-da", + "sha256", + ] + } + if (defined(invoker.ota_args)) { + args += invoker.ota_args + } } } } else if (ti_simplelink_device_family == "cc13x4_26x4") { + if (custom_factory_data) { + pw_python_action("${simplelink_target_name}-without-factory-data.hex") { + public_deps = [ ":${simplelink_target_name}.out.image" ] + + script = "${ti_simplelink_sdk_build_root}/factory_data_trim.py" + sources = [ "${root_out_dir}/${objcopy_image_name}" ] + outputs = + [ "${root_out_dir}/${output_base_name}-without-factory-data.hex" ] + + args = [ + rebase_path("${root_out_dir}/${output_base_name}.hex", + root_out_dir), + rebase_path("${root_out_dir}/${output_base_name}.out.map", + root_out_dir), + rebase_path( + "${root_out_dir}/${output_base_name}-without-factory-data.hex", + root_out_dir), + "cc13x4_26x4", + ] + } + pw_python_action("${simplelink_target_name}-factory-data.hex") { + script = "${ti_simplelink_sdk_build_root}/create_factory_data.py" + sources = [ + "${chip_root}/src/platform/cc13xx_26xx/factory_data.schema", + "${chip_root}/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json", + ] + outputs = [ "${root_out_dir}/${output_base_name}-factory-data.hex" ] + + args = [ + "-factory_data", + rebase_path( + "${chip_root}/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json"), + "-schema", + rebase_path( + "${chip_root}/src/platform/cc13xx_26xx/factory_data.schema"), + "-o", + rebase_path("${root_out_dir}/${output_base_name}-factory-data.hex", + root_out_dir), + "-device", + "cc13x4_26x4", + ] + } + } + # add MCUBoot Header to the executable action("${simplelink_target_name}_header.hex") { - public_deps = [ ":${simplelink_target_name}.out.image" ] + if (custom_factory_data) { + public_deps = + [ ":${simplelink_target_name}-without-factory-data.hex" ] + } else { + public_deps = [ ":${simplelink_target_name}.out.image" ] + } script = "${ti_simplelink_sdk_root}/source/third_party/mcuboot/scripts/imgtool.py" - sources = [ "${root_out_dir}/${output_base_name}.hex" ] + if (custom_factory_data) { + sources = + [ "${root_out_dir}/${output_base_name}-without-factory-data.hex" ] + input_path = + "${root_out_dir}/${output_base_name}-without-factory-data.hex" + } else { + sources = [ "${root_out_dir}/${output_base_name}.hex" ] + input_path = "${root_out_dir}/${output_base_name}.hex" + } outputs = [ "${root_out_dir}/${output_base_name}_header.hex" ] args = [ @@ -222,7 +389,7 @@ template("ti_simplelink_executable") { rebase_path( "${ti_simplelink_sdk_root}/source/third_party/mcuboot/root-ec-p256.pem", root_build_dir), - rebase_path("${root_out_dir}/${output_base_name}.hex", root_out_dir), + rebase_path(input_path, root_out_dir), rebase_path("${root_out_dir}/${output_base_name}_header.hex", root_out_dir), ] @@ -354,21 +521,46 @@ template("ti_simplelink_executable") { ":${simplelink_target_name}_mcubootloader.image", ] - script = "${ti_simplelink_sdk_build_root}/oad_merge_tool.py" - sources = [ - "${root_out_dir}/${output_base_name}.mcubootloader.hex", - "${root_out_dir}/${output_base_name}_header.bin", - ] + if (custom_factory_data) { + public_deps += [ ":${simplelink_target_name}-factory-data.hex" ] + + script = "${ti_simplelink_sdk_build_root}/oad_and_factory_data_merge_tool.py" + sources = [ + "${root_out_dir}/${output_base_name}-factory-data.hex", + "${root_out_dir}/${output_base_name}.mcubootloader.hex", + "${root_out_dir}/${output_base_name}_header.bin", + ] + } else { + script = "${ti_simplelink_sdk_build_root}/oad_merge_tool.py" + sources = [ + "${root_out_dir}/${output_base_name}.mcubootloader.hex", + "${root_out_dir}/${output_base_name}_header.bin", + ] + } + outputs = [ "${root_out_dir}/${output_base_name}-mcuboot.hex" ] - args = [ - rebase_path("${root_out_dir}/${output_base_name}_header.hex", - root_build_dir), - rebase_path("${root_out_dir}/${output_base_name}.mcubootloader.hex", - root_build_dir), - rebase_path("${root_out_dir}/${output_base_name}-mcuboot.hex", - root_build_dir), - ] + if (custom_factory_data) { + args = [ + rebase_path("${root_out_dir}/${output_base_name}_header.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}.mcubootloader.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-factory-data.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-mcuboot.hex", + root_build_dir), + ] + } else { + args = [ + rebase_path("${root_out_dir}/${output_base_name}_header.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}.mcubootloader.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-mcuboot.hex", + root_build_dir), + ] + } } pw_python_action("${target_name}.ota") { # For MCUBoot the image could be truncated to the actual executable @@ -413,6 +605,71 @@ template("ti_simplelink_executable") { } } } + } else if (ti_simplelink_device_family == "cc13x4_26x4" && + custom_factory_data) { + pw_python_action("${simplelink_target_name}-without-factory-data.hex") { + public_deps = [ ":${simplelink_target_name}.out.image" ] + + script = "${ti_simplelink_sdk_build_root}/factory_data_trim.py" + sources = [ "${root_out_dir}/${objcopy_image_name}" ] + outputs = + [ "${root_out_dir}/${output_base_name}-without-factory-data.hex" ] + + args = [ + rebase_path("${root_out_dir}/${output_base_name}.hex", root_out_dir), + rebase_path("${root_out_dir}/${output_base_name}.out.map", + root_out_dir), + rebase_path( + "${root_out_dir}/${output_base_name}-without-factory-data.hex", + root_out_dir), + "cc13x4_26x4", + ] + } + pw_python_action("${simplelink_target_name}-factory-data.hex") { + script = "${ti_simplelink_sdk_build_root}/create_factory_data.py" + sources = [ + "${chip_root}/src/platform/cc13xx_26xx/factory_data.schema", + "${chip_root}/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json", + ] + outputs = [ "${root_out_dir}/${output_base_name}-factory-data.hex" ] + + args = [ + "-factory_data", + rebase_path( + "${chip_root}/src/platform/cc13xx_26xx/factory_data_cc13xx_26xx.json"), + "-schema", + rebase_path( + "${chip_root}/src/platform/cc13xx_26xx/factory_data.schema"), + "-o", + rebase_path("${root_out_dir}/${output_base_name}-factory-data.hex", + root_out_dir), + "-device", + "cc13x4_26x4", + ] + } + pw_python_action("${simplelink_target_name}-and-factory-data.hex") { + public_deps = [ + ":${simplelink_target_name}-factory-data.hex", + ":${simplelink_target_name}-without-factory-data.hex", + ] + script = "${ti_simplelink_sdk_build_root}/factory_data_merge_tool.py" + sources = [ + "${root_out_dir}/${output_base_name}-factory-data.hex", + "${root_out_dir}/${output_base_name}-without-factory-data.hex", + ] + outputs = [ "${root_out_dir}/${output_base_name}-and-factory-data.hex" ] + + args = [ + rebase_path( + "${root_out_dir}/${output_base_name}-without-factory-data.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-factory-data.hex", + root_build_dir), + rebase_path("${root_out_dir}/${output_base_name}-and-factory-data.hex", + root_build_dir), + ] + args += [ "${root_out_dir}/${output_base_name}-and-factory-data.hex" ] + } } group(simplelink_target_name) { From c15abc94fd7ff9df5caf0f95b50314cdf3cbd35e Mon Sep 17 00:00:00 2001 From: Terence Hampson Date: Mon, 8 Jan 2024 14:17:02 -0500 Subject: [PATCH 15/33] Implement updates to IDM test spec for batch commands (#31042) * Implement updates to IDM test spec for batch commands * Restyled by whitespace Restyled by prettier-yaml Restyled by autopep8 * Add another test * Addres PR comments * Restyled by autopep8 * Restyled by isort * Address PR comments * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../suites/certification/Test_TC_IDM_1_1.yaml | 9 - .../suites/certification/Test_TC_IDM_1_3.yaml | 203 ++++++++++++++++++ .../python/chip/clusters/command.cpp | 10 +- src/python_testing/TC_IDM_1_4.py | 186 ++++++++++++++++ 4 files changed, 398 insertions(+), 10 deletions(-) create mode 100644 src/app/tests/suites/certification/Test_TC_IDM_1_3.yaml create mode 100644 src/python_testing/TC_IDM_1_4.py diff --git a/src/app/tests/suites/certification/Test_TC_IDM_1_1.yaml b/src/app/tests/suites/certification/Test_TC_IDM_1_1.yaml index 9994a19196a928..604dd0f2c159fd 100644 --- a/src/app/tests/suites/certification/Test_TC_IDM_1_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_IDM_1_1.yaml @@ -79,15 +79,6 @@ tests: - label: "Step 3: DUT sends the Invoke Request Message to the TH. The Message - should contain multiple paths Path = [[ Endpoint = Endpoint1, Cluster - = ClusterID, Command = Command1 ], [ Endpoint = Endpoint1, Cluster = - ClusterID, Command = Command2 ] ]" - verification: | - Out of Scope - disabled: true - - - label: - "Step 4: DUT sends the Invoke Request Message to the TH. The Message should contain one valid CommandDataIB, which has the specific Endpoint, Specific Cluster and Specific Command. Send 2 more Invoke Request Messages to the TH." diff --git a/src/app/tests/suites/certification/Test_TC_IDM_1_3.yaml b/src/app/tests/suites/certification/Test_TC_IDM_1_3.yaml new file mode 100644 index 00000000000000..3cd059db6e8e73 --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_IDM_1_3.yaml @@ -0,0 +1,203 @@ +# Copyright (c) 2023 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. +# Auto-generated scripts for harness use only, please review before automation. The endpoints and cluster names are currently set to default + +name: + 3.1.3. [TC-IDM-1.3] Batched Commands Invoke Request Action from DUT to TH - + [{DUT_Client}] + +PICS: + - MCORE.IDM.C.InvokeRequest.BatchCommands + +config: + nodeId: 0x12344321 + cluster: "Basic Information" + endpoint: 0 + +tests: + - label: "Note" + verification: | + Chip-repl commands used below are an example to verify the DUT as client test cases. For certification test, we expect DUT should have a capability or way to run the equivalent command. + disabled: true + + - label: "Step 1: DUT sends the Invoke Request Message to the TH. The + Message should contain two valid and unique paths in the + CommandDataIBs, which has the specific Endpoints, specific Clusters + and specific Commands. + + TH should be configured such that it responds to the batched commands + in a single InvokeResponseMessage, the ordering of CommandDataIBs in + the InvokeResponseMessage SHALL be in the same order as provided in + the request." + + verification: | + Product maker needs to provide instructions for how to trigger the command on the DUT that is capable of fitting into a single InvokeResponseMessage. For comparison, the DUT behavior for this + test step can be simulated using chip-repl (when DUT is a commissioner/Client). + The cluster used in the below command is an example, User can use any supported chip cluster/attribute/command. Note in this example the unique path is created by using 2 different endpoints. + + `await devCtrl.SendBatchCommands(0x12344321, [Clusters.Command.InvokeRequestInfo(1, Clusters.OnOff.Commands.Toggle()), Clusters.Command.InvokeRequestInfo(2, Clusters.OnOff.Commands.Toggle())]` + + On TH(all-clusters-app), Verify that the EndpointIDs, CommandIDs, ClusterIDs in the InvokeRequestMessage (as below) matching with the data sent in the above command + + CHIP:DMG: InvokeRequestMessage = + CHIP:DMG: { + CHIP:DMG: suppressResponse = false, + CHIP:DMG: timedRequest = true, + CHIP:DMG: InvokeRequests = + CHIP:DMG: [ + CHIP:DMG: CommandDataIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = <--------- Verifying everything in this struct matches what is provided by product maker + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x1, + CHIP:DMG: ClusterId = 0x6, + CHIP:DMG: CommandId = 0x2, + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: CommandFields = + CHIP:DMG: { + CHIP:DMG: }, + CHIP:DMG: Ref = 0x0, + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: CommandDataIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = <--------- Verifying everything in this struct matches what is provided by product maker + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x2, + CHIP:DMG: ClusterId = 0x6, + CHIP:DMG: CommandId = 0x2, + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: CommandFields = + CHIP:DMG: { + CHIP:DMG: }, + CHIP:DMG: Ref = 0x1, + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: ], + CHIP:DMG: + CHIP:DMG: InteractionModelRevision = 11 + CHIP:DMG: }, + CHIP:DMG: AccessControl: checking f=1 a=c s=0x000000000001B669 t= c=0x0000_0006 e=1 p=o + CHIP:DMG: AccessControl: allowed + disabled: true + + - label: "Step 2: DUT sends the Invoke Request Message to the TH. The + Message should contain two valid and unique paths in the + CommandDataIBs, which has the specific Endpoints, specific Clusters + and specific Commands. + + TH should be configured such that it responds to the batched commands + over two InvokeResponseMessages. The first InvokeResponseMessage SHALL + contain a response to the first CommandDataIB in the + InvokeRequestMessage. The second InvokeReponseMessage SHALL contains a + response to the second CommandDataIB in the InvokeRequestMessage." + + verification: | + Product maker needs to provide instructions for how to trigger the command this on the DUT that is capable of fitting into a single InvokeResponseMessage. For comparison, the DUT behavior for this + test step can be simulated using chip-repl (when DUT is a commissioner/Client). + The cluster used in the below command is an example, User can use any supported chip cluster/attribute/command. Note in this example the unique path is created by using 2 different endpoints. + + `await devCtrl.SendBatchCommands(0x12344321, [Clusters.Command.InvokeRequestInfo(1, Clusters.OnOff.Commands.Toggle()), Clusters.Command.InvokeRequestInfo(2, Clusters.OnOff.Commands.Toggle())]` + + Verify DUT doesn't crash by seeing next step execute. + disabled: true + + - label: "Step 3: DUT sends the Invoke Request Message to the TH. The + Message should contain two valid and unique paths in the + CommandDataIBs, which has the specific Endpoints, specific Clusters + and specific Commands. + + TH should be configured such that it responds to the batched commands + over two InvokeResponseMessages. The first InvokeResponseMessage SHALL + contain a response to the second CommandDataIB in the + InvokeRequestMessage. The second InvokeReponseMessage SHALL contains a + response to the first CommandDataIB in the InvokeRequestMessage." + + verification: | + Product maker needs to provide instructions for how to trigger the command this on the DUT that is capable of fitting into a single InvokeResponseMessage. For comparison, the DUT behavior for this + test step can be simulated using chip-repl (when DUT is a commissioner/Client). + The cluster used in the below command is an example, User can use any supported chip cluster/attribute/command. Note in this example the unique path is created by using 2 different endpoints. + + `await devCtrl.SendBatchCommands(0x12344321, [Clusters.Command.InvokeRequestInfo(1, Clusters.OnOff.Commands.Toggle()), Clusters.Command.InvokeRequestInfo(2, Clusters.OnOff.Commands.Toggle())]` + + Verify DUT doesn't crash by seeing next step execute. + disabled: true + + - label: "Step 4: DUT sends the Invoke Request Message to the TH. The + Message should contain two valid and unique paths in the + CommandDataIBs, which has the specific Endpoints, specific Clusters + and specific Commands. + + TH should be configured such that it responds incorrectly to the + batched commands in a single InvokeResponseMessages. The + InvokeResponseMessage SHALL contain a response to the first + CommandDataIB in the InvokeRequestMessage. The second response to + second CommandDataIB will intentionally be left out." + + verification: | + Product maker needs to provide instructions for how to trigger the command this on the DUT that is capable of fitting into a single InvokeResponseMessage. For comparison, the DUT behavior for this + test step can be simulated using chip-repl (when DUT is a commissioner/Client). + The cluster used in the below command is an example, User can use any supported chip cluster/attribute/command. Note in this example the unique path is created by using 2 different endpoints. + + `await devCtrl.SendBatchCommands(0x12344321, [Clusters.Command.InvokeRequestInfo(1, Clusters.OnOff.Commands.Toggle()), Clusters.Command.InvokeRequestInfo(2, Clusters.OnOff.Commands.Toggle())]` + + Verify DUT doesn't crash by seeing next step execute. + disabled: true + + - label: "Step 5: DUT sends the Invoke Request Message to the TH. The + Message should contain one valid CommandDataIB, which has the specific + Endpoint, Specific Cluster and Specific Command. + + TH should be configured such that it responds regularly to single + invoke request." + + verification: | + Product maker needs to provide instructions for how to trigger the command this on the DUT that is capable of fitting into a single InvokeResponseMessage. For comparison, the DUT behavior for this + test step can be simulated using chip-repl (when DUT is a commissioner/Client). + The cluster used in the below command is an example, User can use any supported chip cluster/attribute/command. Note in this example the unique path is created by using 2 different endpoints. + + `await devCtrl.SendCommands(0x12344321, 1, Clusters.OnOff.Commands.Toggle())` + + On TH(all-clusters-app), Verify that we recieves an InvokeRequestMessage that contains a single InvokeRequests + + CHIP:DMG: InvokeRequestMessage = + CHIP:DMG: { + CHIP:DMG: suppressResponse = false, + CHIP:DMG: timedRequest = true, + CHIP:DMG: InvokeRequests = <--------- Verify only one CommandDataIB in this structure + CHIP:DMG: [ + CHIP:DMG: CommandDataIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x1, + CHIP:DMG: ClusterId = 0x6, + CHIP:DMG: CommandId = 0x2, + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: CommandFields = + CHIP:DMG: { + CHIP:DMG: }, + CHIP:DMG: Ref = 0x0, + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: ], + CHIP:DMG: + CHIP:DMG: InteractionModelRevision = 11 + CHIP:DMG: }, + CHIP:DMG: AccessControl: checking f=1 a=c s=0x000000000001B669 t= c=0x0000_0006 e=1 p=o + CHIP:DMG: AccessControl: allowed + disabled: true diff --git a/src/controller/python/chip/clusters/command.cpp b/src/controller/python/chip/clusters/command.cpp index 168a3cf818eb5b..23f633e27a381b 100644 --- a/src/controller/python/chip/clusters/command.cpp +++ b/src/controller/python/chip/clusters/command.cpp @@ -248,7 +248,15 @@ PyChipError pychip_CommandSender_SendBatchCommands(void * appContext, DeviceProx VerifyOrReturnError(device->GetSecureSession().HasValue(), ToPyChipError(CHIP_ERROR_MISSING_SECURE_SESSION)); auto remoteSessionParameters = device->GetSecureSession().Value()->GetRemoteSessionParameters(); CommandSender::ConfigParameters config; - config.SetRemoteMaxPathsPerInvoke(remoteSessionParameters.GetMaxPathsPerInvoke()); + + // TODO(#30986): Need to create a separate pychip_CommandSender_TestOnlySendBatchCommands so that we perform + // operations that is very clear at callsite that violating certain aspects like setting this MaxPathsPerInvoke + // to a number other than what is reported by the remote node is allowed. Right now the only user of this + // function is cert test script. To implement pychip_CommandSender_TestOnlySendBatchCommands in a clean way + // we need to move away from the variadic arguments. + // config.SetRemoteMaxPathsPerInvoke(remoteSessionParameters.GetMaxPathsPerInvoke()); + (void) remoteSessionParameters; // Still want to get remoteSessionParameters, just wont use it right now. + config.SetRemoteMaxPathsPerInvoke(std::numeric_limits::max()); std::unique_ptr callback = std::make_unique(appContext, /* isBatchedCommands =*/true); diff --git a/src/python_testing/TC_IDM_1_4.py b/src/python_testing/TC_IDM_1_4.py new file mode 100644 index 00000000000000..353349502adffc --- /dev/null +++ b/src/python_testing/TC_IDM_1_4.py @@ -0,0 +1,186 @@ +# +# Copyright (c) 2023 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. +# + +import logging +from dataclasses import dataclass + +import chip.clusters as Clusters +from chip import ChipUtility +from chip.exceptions import ChipStackError +from chip.interaction_model import InteractionModelError, Status +from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main, type_matches +from mobly import asserts + + +@dataclass +class FakeInvalidBasicInformationCommand(Clusters.BasicInformation.Commands.MfgSpecificPing): + @ChipUtility.classproperty + def must_use_timed_invoke(cls) -> bool: + return False + + +class TC_IDM_1_4(MatterBaseTest): + + @async_test_body + async def test_TC_IDM_1_4(self): + dev_ctrl = self.default_controller + dut_node_id = self.dut_node_id + + self.print_step(0, "Commissioning - already done") + + self.print_step(1, "Get remote node's MaxPathsPerInvoke") + session_parameters = dev_ctrl.GetRemoteSessionParameters(dut_node_id) + max_paths_per_invoke = session_parameters.maxPathsPerInvoke + + asserts.assert_greater_equal(max_paths_per_invoke, 1, "Unexpected error returned from unsupported endpoint") + asserts.assert_less_equal(max_paths_per_invoke, 65535, "Unexpected error returned from unsupported endpoint") + + self.print_step(2, "Sending `MaxPathsPerInvoke + 1` InvokeRequest if it fits into single MTU") + # In practice, it was noticed that we could only fit 57 commands before we hit the MTU limit as a result we + # conservatively try putting up to 100 commands into an Invoke request. We are expecting one of 2 things to + # happen if max_paths_per_invoke + 1 is greater than what cap_for_batch_commands is set to: + # 1. Client (TH) fails to send command, since we cannot fit all the commands single MTU. + # When this happens we get ChipStackError with CHIP_ERROR_NO_MEMORY. Test step is skipped + # as per test spec instructions + # 2. Client (TH) able to send command. While unexpected we will hit two different test failure depending on + # what the server does. + # a. Server successfully handle command and send InvokeResponse with results of all individual commands + # being failure. In this case, test fails on unexpected successes like this + # b. Server fails to handle command that is between cap_for_batch_commands and max_paths_per_invoke + 1. + # In this case, test fails as device should have actually succeeded and been caught in 2.a. + cap_for_batch_commands = 100 + number_of_commands_to_send = min(max_paths_per_invoke + 1, cap_for_batch_commands) + + invalid_command_id = 0xffff_ffff + list_of_commands_to_send = [] + for endpoint_index in range(number_of_commands_to_send): + # Using Toggle command to form the base as it is a command that doesn't take + # any arguments, this allows us to fit as more requests into single MTU. + invalid_command = Clusters.OnOff.Commands.Toggle() + # This is how we make the command invalid + invalid_command.command_id = invalid_command_id + + list_of_commands_to_send.append(Clusters.Command.InvokeRequestInfo(endpoint_index, invalid_command)) + + asserts.assert_greater_equal(len(list_of_commands_to_send), 2, + "Step 2 is always expected to try sending at least 2 command, something wrong with test logic") + try: + await dev_ctrl.SendBatchCommands(dut_node_id, list_of_commands_to_send) + # If you get the assert below it is likely because cap_for_batch_commands is actually too low. + # This might happen after TCP is enabled and DUT supports TCP. + asserts.fail( + f"Unexpected success return from sending too many commands, we sent {number_of_commands_to_send}, test capped at {cap_for_batch_commands}") + except InteractionModelError as e: + # This check is for 2.a., mentioned above introduction of variable cap_for_batch_commands. + asserts.assert_equal(number_of_commands_to_send, max_paths_per_invoke + 1, + "Test didn't send as many command as max_paths_per_invoke + 1, likely due to MTU cap_for_batch_commands, but we still got an error from server. This should have been a success from server") + asserts.assert_equal(e.status, Status.InvalidAction, + "DUT sent back an unexpected error, we were expecting InvalidAction") + self.print_step(2, "DUT successfully failed to process `MaxPathsPerInvoke + 1` InvokeRequests") + except ChipStackError as e: + chip_error_no_memory = 0x0b + asserts.assert_equal(e.err, chip_error_no_memory, "Unexpected error while trying to send InvokeRequest") + # TODO it is possible we want to confirm DUT can handle up to MTU max. But that is not in test plan as of right now. + # Additionally CommandSender is not currently set up to enable caller to fill up to MTU. This might be coming soon, + # just that it is not supported today. + self.print_step(2, "DUTs reported MaxPathsPerInvoke + 1 is larger than what fits into MTU. Test step is skipped") + + if max_paths_per_invoke == 1: + # TODO(#31139) After issue is resolved use that API properly to mark tests steps as skipped + self.print_step(3, "Skipping test step as max_paths_per_invoke == 1") + self.print_step(4, "Skipping test step as max_paths_per_invoke == 1") + self.print_step(5, "Skipping test step as max_paths_per_invoke == 1") + self.print_step(6, "Skipping test step as max_paths_per_invoke == 1") + self.print_step(7, "Skipping test step as max_paths_per_invoke == 1") + self.print_step(8, "Skipping test step as max_paths_per_invoke == 1") + self.print_step(9, "Skipping test step as max_paths_per_invoke == 1") + else: + await self.steps_3_to_9(False) + + async def steps_3_to_9(self, dummy_value): + dev_ctrl = self.default_controller + dut_node_id = self.dut_node_id + + self.print_step(3, "Sending sending two InvokeRequest with idential paths") + command = Clusters.BasicInformation.Commands.MfgSpecificPing() + endpoint = 0 + invoke_request_1 = Clusters.Command.InvokeRequestInfo(endpoint, command) + try: + result = await dev_ctrl.SendBatchCommands(dut_node_id, [invoke_request_1, invoke_request_1]) + asserts.fail("Unexpected success return after sending two identical (non-unique) paths in the InvokeRequest") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.InvalidAction, + "DUT sent back an unexpected error, we were expecting InvalidAction") + logging.info("DUT successfully failed to process two InvokeRequests that contains non-unique paths") + + self.print_step(4, "Skipping test until https://github.com/project-chip/connectedhomeip/issues/30986 resolved") + + self.print_step(5, "Verify DUT is able to responsed to InvokeRequestMessage that contains two valid paths") + endpoint = 0 + command = Clusters.OperationalCredentials.Commands.CertificateChainRequest( + Clusters.OperationalCredentials.Enums.CertificateChainTypeEnum.kDACCertificate) + invoke_request_1 = Clusters.Command.InvokeRequestInfo(endpoint, command) + + command = Clusters.GroupKeyManagement.Commands.KeySetRead(0) + invoke_request_2 = Clusters.Command.InvokeRequestInfo(endpoint, command) + try: + result = await dev_ctrl.SendBatchCommands(dut_node_id, [invoke_request_1, invoke_request_2]) + asserts.assert_true(type_matches(result, list), "Unexpected return from SendBatchCommands") + asserts.assert_equal(len(result), 2, "Unexpected number of InvokeResponses sent back from DUT") + asserts.assert_true(type_matches( + result[0], Clusters.OperationalCredentials.Commands.CertificateChainResponse), "Unexpected return type for first InvokeRequest") + asserts.assert_true(type_matches( + result[1], Clusters.GroupKeyManagement.Commands.KeySetReadResponse), "Unexpected return type for second InvokeRequest") + self.print_step(5, "DUT successfully responded to a InvokeRequest action with two valid commands") + except InteractionModelError: + asserts.fail("DUT failed to successfully responded to a InvokeRequest action with two valid commands") + + self.print_step(6, "Skipping test until https://github.com/project-chip/connectedhomeip/issues/30991 resolved") + + self.print_step(7, "Skipping test until https://github.com/project-chip/connectedhomeip/issues/30986 resolved") + + self.print_step(8, "Verify DUT is able to responsed to InvokeRequestMessage that contains two valid paths. One of which requires timed invoke, and TimedRequest in InvokeResponseMessage set to true") + endpoint = 0 + command = Clusters.GroupKeyManagement.Commands.KeySetRead(0) + invoke_request_1 = Clusters.Command.InvokeRequestInfo(endpoint, command) + + command = Clusters.AdministratorCommissioning.Commands.RevokeCommissioning() + invoke_request_2 = Clusters.Command.InvokeRequestInfo(endpoint, command) + try: + result = await dev_ctrl.SendBatchCommands(dut_node_id, [invoke_request_1, invoke_request_2], timedRequestTimeoutMs=5000) + asserts.assert_true(type_matches(result, list), "Unexpected return from SendBatchCommands") + asserts.assert_equal(len(result), 2, "Unexpected number of InvokeResponses sent back from DUT") + asserts.assert_true(type_matches( + result[0], Clusters.GroupKeyManagement.Commands.KeySetReadResponse), "Unexpected return type for first InvokeRequest") + asserts.assert_true(type_matches(result[1], InteractionModelError), "Unexpected return type for second InvokeRequest") + + # We sent out RevokeCommissioning without an ArmSafe intentionally, confirm that it failed for that reason. + asserts.assert_equal(result[1].status, Status.Failure, + "Timed command, RevokeCommissioning, didn't fail in manner expected by test") + window_not_open_cluster_error = 4 + asserts.assert_equal(result[1].clusterStatus, window_not_open_cluster_error, + "Timed command, RevokeCommissioning, failed with incorrect cluster code") + self.print_step( + 8, "DUT successfully responded to a InvokeRequest action with two valid commands. One of which required timed invoke, and TimedRequest in InvokeResponseMessage was set to true") + except InteractionModelError: + asserts.fail("DUT failed to successfully responded to a InvokeRequest action with two valid commands") + + self.print_step(9, "Skipping test until https://github.com/project-chip/connectedhomeip/issues/30986 resolved") + + +if __name__ == "__main__": + default_matter_test_main() From 7b237e8fa6ebeb9e0b12196613e6c816aa6211e8 Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Mon, 8 Jan 2024 11:19:13 -0800 Subject: [PATCH 16/33] Fix JNI Typo for UnpairDeviceCallback.OnError (#31300) --- src/controller/java/AndroidCurrentFabricRemover.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/java/AndroidCurrentFabricRemover.cpp b/src/controller/java/AndroidCurrentFabricRemover.cpp index 4c4ab28412719c..1029177ae3db31 100644 --- a/src/controller/java/AndroidCurrentFabricRemover.cpp +++ b/src/controller/java/AndroidCurrentFabricRemover.cpp @@ -38,7 +38,7 @@ AndroidCurrentFabricRemover::AndroidCurrentFabricRemover(DeviceController * cont env->ExceptionClear(); } - mOnErrorMethod = env->GetMethodID(callbackClass, "onError", "(JI)V"); + mOnErrorMethod = env->GetMethodID(callbackClass, "onError", "(IJ)V"); if (mOnErrorMethod == nullptr) { ChipLogError(Controller, "Failed to access callback 'onError' method"); From 19ba3d92ce6ee72d31b00df6abb547d298650950 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Tue, 9 Jan 2024 04:32:42 +0900 Subject: [PATCH 17/33] [ICD][Android] Add ICD storage API, UI (#31193) * Add ICD Client Storage * Add icd list command in java controller * Restyled by google-java-format * Restyled by clang-format * Modify kotlin codestyle * Restyled by google-java-format * Change from comments * Add symmetric Key parameter * Kotlin code style * Restyled by clang-format * Fix kotlin_controller build error * Restyle in kotlin * Update ICDRegistrationComplete callback * Restyled by google-java-format * Restyled by clang-format * Fix Darwin build error * Restyled by clang-format * Modify using GetLocalClassRef * Update error variable * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../chiptool/GenericChipDeviceListener.kt | 8 +- .../chip/chiptool/SelectActionFragment.kt | 5 + .../chiptool/clusterclient/ICDFragment.kt | 61 ++++++++++ .../DeviceProvisioningFragment.kt | 16 ++- .../src/main/res/layout/i_c_d_fragment.xml | 29 +++++ .../res/layout/select_action_fragment.xml | 8 ++ .../app/src/main/res/values/strings.xml | 2 + examples/java-matter-controller/BUILD.gn | 1 + .../java/src/com/matter/controller/Main.kt | 11 ++ .../controller/commands/icd/ICDListCommand.kt | 62 +++++++++++ .../commands/pairing/PairingCommand.kt | 13 ++- .../commands/pairing/PairingCommand.kt | 13 ++- .../java/AndroidDeviceControllerWrapper.cpp | 80 ++++++++++++- .../java/AndroidDeviceControllerWrapper.h | 6 + src/controller/java/BUILD.gn | 2 + .../java/CHIPDeviceController-JNI.cpp | 82 ++++++++++++-- .../ChipDeviceController.java | 23 +++- .../chip/devicecontroller/ICDClientInfo.java | 105 ++++++++++++++++++ .../chip/devicecontroller/ICDDeviceInfo.java | 32 ++++++ .../controller/CompletionListenerAdapter.kt | 9 +- .../src/matter/controller/MatterController.kt | 8 +- 21 files changed, 545 insertions(+), 31 deletions(-) create mode 100644 examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/ICDFragment.kt create mode 100644 examples/android/CHIPTool/app/src/main/res/layout/i_c_d_fragment.xml create mode 100644 examples/java-matter-controller/java/src/com/matter/controller/commands/icd/ICDListCommand.kt create mode 100644 src/controller/java/src/chip/devicecontroller/ICDClientInfo.java create mode 100644 src/controller/java/src/chip/devicecontroller/ICDDeviceInfo.java diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt index 12e17998fa7c15..e4542fc518e9a8 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/GenericChipDeviceListener.kt @@ -1,6 +1,7 @@ package com.google.chip.chiptool import chip.devicecontroller.ChipDeviceController +import chip.devicecontroller.ICDDeviceInfo open class GenericChipDeviceListener : ChipDeviceController.CompletionListener { override fun onConnectDeviceComplete() { @@ -56,7 +57,12 @@ open class GenericChipDeviceListener : ChipDeviceController.CompletionListener { // No op } - override fun onICDRegistrationComplete(icdNodeId: Long, icdCounter: Long) { + override fun onICDRegistrationComplete( + errorCode: Int, + icdNodeId: Long, + icdCounter: Long, + icdDeviceInfo: ICDDeviceInfo + ) { // No op } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt index dc082d5dc5b73c..a597bd934514e7 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt @@ -74,6 +74,7 @@ class SelectActionFragment : Fragment() { binding.unpairDeviceBtn.setOnClickListener { handleUnpairDeviceClicked() } binding.groupSettingBtn.setOnClickListener { handleGroupSettingClicked() } binding.otaProviderBtn.setOnClickListener { handleOTAProviderClicked() } + binding.icdBtn.setOnClickListener { handleICDClicked() } return binding.root } @@ -244,6 +245,10 @@ class SelectActionFragment : Fragment() { showFragment(GroupSettingFragment.newInstance()) } + private fun handleICDClicked() { + showFragment(ICDFragment.newInstance()) + } + companion object { @JvmStatic fun newInstance() = SelectActionFragment() diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/ICDFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/ICDFragment.kt new file mode 100644 index 00000000000000..3b27f58c3af575 --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/ICDFragment.kt @@ -0,0 +1,61 @@ +package com.google.chip.chiptool.clusterclient + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import chip.devicecontroller.ChipDeviceController +import com.google.chip.chiptool.ChipClient +import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.ICDFragmentBinding +import kotlinx.coroutines.CoroutineScope + +class ICDFragment : Fragment() { + private val deviceController: ChipDeviceController + get() = ChipClient.getDeviceController(requireContext()) + + private lateinit var scope: CoroutineScope + + private lateinit var addressUpdateFragment: AddressUpdateFragment + + private var _binding: ICDFragmentBinding? = null + private val binding + get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = ICDFragmentBinding.inflate(inflater, container, false) + scope = viewLifecycleOwner.lifecycleScope + + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + + val clientInfo = deviceController.icdClientInfo + var msg = "" + + for (info in clientInfo) { + msg += "$info\n" + } + showMessage(msg) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + private fun showMessage(msg: String) { + requireActivity().runOnUiThread { binding.icdTv.text = msg } + } + + companion object { + fun newInstance(): ICDFragment = ICDFragment() + } +} diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt index 16a411bc5eba05..88c9965d31f658 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/DeviceProvisioningFragment.kt @@ -32,6 +32,7 @@ import androidx.lifecycle.lifecycleScope import chip.devicecontroller.AttestationInfo import chip.devicecontroller.ChipDeviceController import chip.devicecontroller.DeviceAttestationDelegate +import chip.devicecontroller.ICDDeviceInfo import chip.devicecontroller.ICDRegistrationInfo import chip.devicecontroller.NetworkCredentials import com.google.chip.chiptool.ChipClient @@ -293,11 +294,22 @@ class DeviceProvisioningFragment : Fragment() { ) } - override fun onICDRegistrationComplete(icdNodeId: Long, icdCounter: Long) { - Log.d(TAG, "onICDRegistrationComplete - icdNodeId : $icdNodeId, icdCounter : $icdCounter") + override fun onICDRegistrationComplete( + errorCode: Int, + icdNodeId: Long, + icdCounter: Long, + icdDeviceInfo: ICDDeviceInfo + ) { + Log.d( + TAG, + "onICDRegistrationComplete - errorCode: $errorCode, icdNodeId : $icdNodeId, icdCounter : $icdCounter, symmetricKey : ${icdDeviceInfo.symmetricKey.toHex()}" + ) } } + private fun ByteArray.toHex(): String = + joinToString(separator = "") { eachByte -> "%02x".format(eachByte) } + /** Callback from [DeviceProvisioningFragment] notifying any registered listeners. */ interface Callback { /** Notifies that commissioning has been completed. */ diff --git a/examples/android/CHIPTool/app/src/main/res/layout/i_c_d_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/i_c_d_fragment.xml new file mode 100644 index 00000000000000..6fb4e0fc35b6ca --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/res/layout/i_c_d_fragment.xml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml index 2ec36b43128be4..5824e8061a4e03 100644 --- a/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml +++ b/examples/android/CHIPTool/app/src/main/res/layout/select_action_fragment.xml @@ -127,6 +127,14 @@ android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:text="@string/ota_provider_btn_text" /> + +