diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml index f10377e4bc63db..6438d540ad0b7a 100644 --- a/.github/workflows/examples-efr32.yaml +++ b/.github/workflows/examples-efr32.yaml @@ -109,6 +109,17 @@ jobs: /tmp/bloat_reports/ - name: Clean out build output run: rm -rf ./out + - name: Build BRD4338A variants + run: | + ./scripts/run_in_build_env.sh \ + "./scripts/build/build_examples.py \ + --enable-flashbundle \ + --target efr32-brd4338a-light-wifi-917_soc-skip_rps_generation \ + build \ + --copy-artifacts-to out/artifacts \ + " + - name: Clean out build output + run: rm -rf ./out - name: Build example EFR32+WF200 WiFi Lock app for BRD4161A run: | scripts/examples/gn_silabs_example.sh examples/lock-app/silabs out/lock_app_wifi_wf200 BRD4161A is_debug=false chip_logging=false --wifi wf200 --docker diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index a476dac7cd7009..e92fbc485d3753 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -487,10 +487,12 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCRUNM_1_2.py" --script-args "--int-arg PIXIT_ENDPOINT:1 --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestMatterTestingSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestConformanceSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestSpecParsingSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-lock-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-lock-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_DRLK_2_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-lock-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-lock-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_DRLK_2_3.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-lock-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-lock-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_DRLK_2_12.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/TestTimeSyncTrustedTimeSourceRunner.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TC_AccessChecker.py" --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' - name: Uploading core files uses: actions/upload-artifact@v4 if: ${{ failure() && !env.ACT }} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6d6c19e3f2b62f..6e9983700a0df7 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -605,6 +605,7 @@ "efr32-brd4186a-window-covering", "efr32-brd4187a-window-covering", "efr32-brd4304a-window-covering", + "efr32-brd4338a-light-wifi-917_soc-skip_rps_generation", "esp32-c3devkit-all-clusters", "esp32-devkitc-all-clusters", "esp32-devkitc-all-clusters-ipv6only", diff --git a/data_model/clusters/ConcentrationMeasurement.xml b/data_model/clusters/ConcentrationMeasurement.xml index 96cfe071cdc8c4..7351a0951e003f 100644 --- a/data_model/clusters/ConcentrationMeasurement.xml +++ b/data_model/clusters/ConcentrationMeasurement.xml @@ -1,61 +1,61 @@ - - + diff --git a/data_model/clusters/ResourceMonitoring.xml b/data_model/clusters/ResourceMonitoring.xml index d79c9a543f0a20..8ac1186f7b3a99 100644 --- a/data_model/clusters/ResourceMonitoring.xml +++ b/data_model/clusters/ResourceMonitoring.xml @@ -1,61 +1,61 @@ - - + diff --git a/data_model/clusters/WaterContentMeasurement.xml b/data_model/clusters/WaterContentMeasurement.xml index d2e29bca2aac53..15b613015444cb 100644 --- a/data_model/clusters/WaterContentMeasurement.xml +++ b/data_model/clusters/WaterContentMeasurement.xml @@ -1,4 +1,4 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +--> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/guides/ti/images/cc13x2_memmap.png b/docs/guides/ti/images/cc13x2_memmap.png new file mode 100644 index 00000000000000..a89aee7837e3aa Binary files /dev/null and b/docs/guides/ti/images/cc13x2_memmap.png differ diff --git a/docs/guides/ti/images/cc13x4_memmap.png b/docs/guides/ti/images/cc13x4_memmap.png new file mode 100644 index 00000000000000..4442c6352efbc9 Binary files /dev/null and b/docs/guides/ti/images/cc13x4_memmap.png differ diff --git a/docs/guides/ti/images/factory_data_overview.png b/docs/guides/ti/images/factory_data_overview.png new file mode 100644 index 00000000000000..f2718ce708f854 Binary files /dev/null and b/docs/guides/ti/images/factory_data_overview.png differ 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/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 3138b9f7dc831f..5e68b8ba48387e 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 @@ -6200,6 +6200,10 @@ internal cluster UnitTesting = 4294048773 { NestedStructList arg1[] = 0; } + response struct TestBatchHelperResponse = 12 { + octet_string<800> buffer = 0; + } + request struct TestListInt8UReverseRequestRequest { int8u arg1[] = 0; } @@ -6246,6 +6250,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 */ @@ -6311,6 +6327,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). */ @@ -8015,6 +8035,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 b618902573750c..21af50a92d1c98 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": [ @@ -19326,6 +19326,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-app/all-clusters-common/include/operational-state-delegate-impl.h b/examples/all-clusters-app/all-clusters-common/include/operational-state-delegate-impl.h index fda27fafbe3b71..c8d63c2bb6efc2 100644 --- a/examples/all-clusters-app/all-clusters-common/include/operational-state-delegate-impl.h +++ b/examples/all-clusters-app/all-clusters-common/include/operational-state-delegate-impl.h @@ -50,14 +50,18 @@ class GenericOperationalStateDelegateImpl : public Delegate CHIP_ERROR GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) override; /** - * Fills in the provided GenericOperationalPhase with the phase at index `index` if there is one, + * Fills in the provided MutableCharSpan with the phase at index `index` if there is one, * or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of phases. + * + * If CHIP_ERROR_NOT_FOUND is returned for index 0, that indicates that the PhaseList attribute is null + * (there are no phases defined at all). + * * Note: This is used by the SDK to populate the phase list attribute. If the contents of this list changes, the * device SHALL call the Instance's ReportPhaseListChange method to report that this attribute has changed. * @param index The index of the phase, with 0 representing the first phase. - * @param operationalPhase The GenericOperationalPhase is filled. + * @param operationalPhase The MutableCharSpan is filled. */ - CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase) override; + CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) override; // command callback /** @@ -86,7 +90,7 @@ class GenericOperationalStateDelegateImpl : public Delegate protected: Span mOperationalStateList; - Span mOperationalPhaseList; + Span mOperationalPhaseList; }; // This is an application level delegate to handle operational state commands according to the specific business logic. @@ -100,22 +104,45 @@ class OperationalStateDelegate : public GenericOperationalStateDelegateImpl GenericOperationalState(to_underlying(OperationalStateEnum::kError)), }; - const GenericOperationalPhase opPhaseList[1] = { - // Phase List is null - GenericOperationalPhase(DataModel::Nullable()), - }; - public: OperationalStateDelegate() { GenericOperationalStateDelegateImpl::mOperationalStateList = Span(opStateList); - GenericOperationalStateDelegateImpl::mOperationalPhaseList = Span(opPhaseList); } }; void Shutdown(); } // namespace OperationalState + +namespace RvcOperationalState { + +// This is an application level delegate to handle operational state commands according to the specific business logic. +class RvcOperationalStateDelegate : public OperationalState::GenericOperationalStateDelegateImpl +{ +private: + const OperationalState::GenericOperationalState rvcOpStateList[7] = { + OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)), + OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kRunning)), + OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kPaused)), + OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kError)), + OperationalState::GenericOperationalState( + to_underlying(Clusters::RvcOperationalState::OperationalStateEnum::kSeekingCharger)), + OperationalState::GenericOperationalState(to_underlying(Clusters::RvcOperationalState::OperationalStateEnum::kCharging)), + OperationalState::GenericOperationalState(to_underlying(Clusters::RvcOperationalState::OperationalStateEnum::kDocked)), + }; + +public: + RvcOperationalStateDelegate() + { + GenericOperationalStateDelegateImpl::mOperationalStateList = + Span(rvcOpStateList); + } +}; + +void Shutdown(); + +} // namespace RvcOperationalState } // namespace Clusters } // namespace app } // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp b/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp index 0e819dbfb482dc..8c203b1f23955d 100644 --- a/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp @@ -33,14 +33,13 @@ CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalStateAtIndex(size_ return CHIP_NO_ERROR; } -CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase) +CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) { if (index >= mOperationalPhaseList.size()) { return CHIP_ERROR_NOT_FOUND; } - operationalPhase = mOperationalPhaseList[index]; - return CHIP_NO_ERROR; + return CopyCharSpanToMutableCharSpan(mOperationalPhaseList[index], operationalPhase); } void GenericOperationalStateDelegateImpl::HandlePauseStateCallback(GenericOperationalError & err) diff --git a/examples/all-clusters-app/ameba/main/OperationalStateManager.cpp b/examples/all-clusters-app/ameba/main/OperationalStateManager.cpp index 68ee456aee9461..8dbeda60d75526 100644 --- a/examples/all-clusters-app/ameba/main/OperationalStateManager.cpp +++ b/examples/all-clusters-app/ameba/main/OperationalStateManager.cpp @@ -33,14 +33,13 @@ CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalStateAtIndex(size_ return CHIP_NO_ERROR; } -CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase) +CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) { if (index >= mOperationalPhaseList.size()) { return CHIP_ERROR_NOT_FOUND; } - operationalPhase = mOperationalPhaseList[index]; - return CHIP_NO_ERROR; + return CopyCharSpanToMutableCharSpan(mOperationalPhaseList[index], operationalPhase); } void GenericOperationalStateDelegateImpl::HandlePauseStateCallback(GenericOperationalError & err) diff --git a/examples/all-clusters-app/ameba/main/include/OperationalStateManager.h b/examples/all-clusters-app/ameba/main/include/OperationalStateManager.h index 875534cc93638d..2183e92078e6c7 100644 --- a/examples/all-clusters-app/ameba/main/include/OperationalStateManager.h +++ b/examples/all-clusters-app/ameba/main/include/OperationalStateManager.h @@ -54,14 +54,18 @@ class GenericOperationalStateDelegateImpl : public Delegate CHIP_ERROR GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) override; /** - * Fills in the provided GenericOperationalPhase with the phase at index `index` if there is one, + * Fills in the provided MutableCharSpan with the phase at index `index` if there is one, * or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of phases. + * + * If CHIP_ERROR_NOT_FOUND is returned for index 0, that indicates that the PhaseList attribute is null + * (there are no phases defined at all). + * * Note: This is used by the SDK to populate the phase list attribute. If the contents of this list changes, the * device SHALL call the Instance's ReportPhaseListChange method to report that this attribute has changed. * @param index The index of the phase, with 0 representing the first phase. - * @param operationalPhase The GenericOperationalPhase is filled. + * @param operationalPhase The MutableCharSpan is filled. */ - CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase) override; + CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) override; // command callback /** @@ -90,7 +94,7 @@ class GenericOperationalStateDelegateImpl : public Delegate protected: Span mOperationalStateList; - Span mOperationalPhaseList; + Span mOperationalPhaseList; }; // This is an application level delegate to handle operational state commands according to the specific business logic. @@ -104,16 +108,10 @@ class OperationalStateDelegate : public GenericOperationalStateDelegateImpl GenericOperationalState(to_underlying(OperationalStateEnum::kError)), }; - const GenericOperationalPhase opPhaseList[1] = { - // Phase List is null - GenericOperationalPhase(DataModel::Nullable()), - }; - public: OperationalStateDelegate() { GenericOperationalStateDelegateImpl::mOperationalStateList = Span(opStateList); - GenericOperationalStateDelegateImpl::mOperationalPhaseList = Span(opPhaseList); } }; @@ -140,18 +138,11 @@ class RvcOperationalStateDelegate : public OperationalState::GenericOperationalS OperationalState::GenericOperationalState(to_underlying(Clusters::RvcOperationalState::OperationalStateEnum::kDocked)), }; - const OperationalState::GenericOperationalPhase rvcOpPhaseList[1] = { - // Phase List is null - OperationalState::GenericOperationalPhase(DataModel::Nullable()), - }; - public: RvcOperationalStateDelegate() { GenericOperationalStateDelegateImpl::mOperationalStateList = Span(rvcOpStateList); - GenericOperationalStateDelegateImpl::mOperationalPhaseList = - Span(rvcOpPhaseList); } }; 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/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/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" /> + +