From 5f1a60bf105a476173f1c4f5e8f298d36423ae1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Ba=C5=82ys?= Date: Tue, 16 May 2023 07:15:22 +0200 Subject: [PATCH] [nrfconnect] Added the Device Appearance attribute to factory data (#26473) The appearance attribute of the Basic Information cluster has been added to the Factory Data set. That field allows for defining the visible finish of the product's external case finish method, and color hue. - The attribute has been added to the factory data provider and the Factory Data Parser. - The appearance field has been described in the factory data guide. --- .../chip-module/generate_factory_data.cmake | 5 + config/zephyr/Kconfig | 17 +++ .../nrfconnect_factory_data_configuration.md | 137 ++++++++++++------ .../generate_nrfconnect_chip_factory_data.py | 12 ++ .../nrfconnect/nrfconnect_factory_data.schema | 10 ++ .../tests/test_generate_factory_data.py | 4 + src/platform/nrfconnect/FactoryDataParser.c | 25 +++- src/platform/nrfconnect/FactoryDataParser.h | 5 +- .../nrfconnect/FactoryDataProvider.cpp | 21 +++ src/platform/nrfconnect/FactoryDataProvider.h | 2 + 10 files changed, 189 insertions(+), 49 deletions(-) diff --git a/config/nrfconnect/chip-module/generate_factory_data.cmake b/config/nrfconnect/chip-module/generate_factory_data.cmake index a754f22873c13d..491411cb6a3dd4 100644 --- a/config/nrfconnect/chip-module/generate_factory_data.cmake +++ b/config/nrfconnect/chip-module/generate_factory_data.cmake @@ -90,6 +90,11 @@ string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n") string(APPEND script_args "--include_passcode\n") string(APPEND script_args "--overwrite\n") +string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n") + +if(CONFIG_CHIP_DEVICE_PRODUCT_COLOR) + string(APPEND script_args "--product_color ${CONFIG_CHIP_DEVICE_PRODUCT_COLOR}\n") +endif() if(CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES) string(APPEND script_args "--generate_onboarding\n") diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index b1edad054824c7..f0e8d9eddfcb66 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -201,6 +201,23 @@ config CHIP_DEVICE_ENABLE_KEY test action. This value is used during certification tests, and should not be present on devices in production environment. +config CHIP_DEVICE_PRODUCT_FINISH + string "Description of the product's external case finish method" + default "other" + help + provides a description of the product's external case finish method. + Possible values: + other; matte; satin; polished; rugged; fabric + +config CHIP_DEVICE_PRODUCT_COLOR + string "Description of the product's primary color" + help + provides a description of the product's primary color. + Possible values: + black; navy; green; teal; maroon; purple; olive; gray; blue; lime; + aqua; red; fuchsia; yellow; white; nickel; chrome; brass; cooper; + silver; gold. + # Matter optional features and parameters config CHIP_ENABLE_PAIRING_AUTOSTART diff --git a/docs/guides/nrfconnect_factory_data_configuration.md b/docs/guides/nrfconnect_factory_data_configuration.md index 16a9210c41fb8c..59eb99b50ad101 100644 --- a/docs/guides/nrfconnect_factory_data_configuration.md +++ b/docs/guides/nrfconnect_factory_data_configuration.md @@ -30,27 +30,29 @@ data secure by applying hardware write protection.
-- [Overview](#overview) - - [Factory data component table](#factory-data-component-table) - - [Factory data format](#factory-data-format) -- [Enabling factory data support](#enabling-factory-data-support) -- [Generating factory data](#generating-factory-data) - - [Creating the factory data JSON file with the first script](#creating-the-factory-data-json-file-with-the-first-script) - - [How to set user data](#how-to-set-user-data) - - [How to handle user data](#how-to-handle-user-data) - - [Verifying using the JSON Schema tool](#verifying-using-the-json-schema-tool) - - [Option 1: Using the php-json-schema tool](#option-1-using-the-php-json-schema-tool) - - [Option 2: Using a website validator](#option-2-using-a-website-validator) - - [Option 3: Using the nRF Connect Python script](#option-3-using-the-nrf-connect-python-script) - - [Generating onboarding codes](#generating-onboarding-codes) - - [Enabling onboarding codes generation within the build system](#enabling-onboarding-codes-generation-within-the-build-system) - - [Preparing factory data partition on a device](#preparing-factory-data-partition-on-a-device) - - [Creating a factory data partition with the second script](#creating-a-factory-data-partition-with-the-second-script) -- [Building an example with factory data](#building-an-example-with-factory-data) - - [Providing factory data parameters as a build argument list](#providing-factory-data-parameters-as-a-build-argument-list) - - [Setting factory data parameters using interactive Kconfig interfaces](#setting-factory-data-parameters-using-interactive-kconfig-interfaces) -- [Programming factory data](#programming-factory-data) -- [Using own factory data implementation](#using-own-factory-data-implementation) +- [Configuring factory data for the nRF Connect examples](#configuring-factory-data-for-the-nrf-connect-examples) + - [Overview](#overview) + - [Factory data component table](#factory-data-component-table) + - [Factory data format](#factory-data-format) + - [Appearance field description](#appearance-field-description) + - [Enabling factory data support](#enabling-factory-data-support) + - [Generating factory data](#generating-factory-data) + - [Creating the factory data JSON file with the first script](#creating-the-factory-data-json-file-with-the-first-script) + - [How to set user data](#how-to-set-user-data) + - [How to handle user data](#how-to-handle-user-data) + - [Verifying using the JSON Schema tool](#verifying-using-the-json-schema-tool) + - [Option 1: Using the php-json-schema tool](#option-1-using-the-php-json-schema-tool) + - [Option 2: Using a website validator](#option-2-using-a-website-validator) + - [Option 3: Using the nRF Connect Python script](#option-3-using-the-nrf-connect-python-script) + - [Generating onboarding codes](#generating-onboarding-codes) + - [Enabling onboarding codes generation within the build system](#enabling-onboarding-codes-generation-within-the-build-system) + - [Preparing factory data partition on a device](#preparing-factory-data-partition-on-a-device) + - [Creating a factory data partition with the second script](#creating-a-factory-data-partition-with-the-second-script) + - [Building an example with factory data](#building-an-example-with-factory-data) + - [Providing factory data parameters as a build argument list](#providing-factory-data-parameters-as-a-build-argument-list) + - [Setting factory data parameters using interactive Kconfig interfaces](#setting-factory-data-parameters-using-interactive-kconfig-interfaces) + - [Programming factory data](#programming-factory-data) + - [Using own factory data implementation](#using-own-factory-data-implementation)
@@ -87,27 +89,28 @@ about The following table lists the parameters of a factory data set: -| Key name | Full name | Length | Format | Conformance | Description | -| :---------------: | :----------------------------------: | :--------: | :----------: | :---------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| `version` | factory data version | 2 B | uint16 | mandatory | A version of the current factory data set. It cannot be changed by a user and it must be coherent with current version of the Factory Data Provider on device side. | -| `sn` | serial number | <1, 32> B | ASCII string | mandatory | A serial number parameter defines an unique number of manufactured device. The maximum length of the serial number is 32 characters. | -| `vendor_id` | vendor ID | 2 B | uint16 | mandatory | A CSA-assigned ID for the organization responsible for producing the device. | -| `product_id` | product ID | 2 B | uint16 | mandatory | A unique ID assigned by the device vendor to identify the product. It defaults to a CSA-assigned ID that designates a non-production or test product. | -| `vendor_name` | vendor name | <1, 32> B | ASCII string | mandatory | A human-readable vendor name that provides a simple string containing identification of device's vendor for the application and Matter stack purposes. | -| `product_name` | product name | <1, 32> B | ASCII string | mandatory | A human-readable product name that provides a simple string containing identification of the product for the application and the Matter stack purposes. | -| `date` | manufacturing date | <8, 10> B | ISO 8601 | mandatory | A manufacturing date specifies the date that the device was manufactured. The date format used is ISO 8601, for example `YYYY-MM-DD`. | -| `hw_ver` | hardware version | 2 B | uint16 | mandatory | A hardware version number that specifies the version number of the hardware of the device. The value meaning and the versioning scheme is defined by the vendor. | -| `hw_ver_str` | hardware version string | <1, 64> B | uint16 | mandatory | A hardware version string parameter that specifies the version of the hardware of the device as a more user-friendly value than that presented by the hardware version integer value. The value meaning and the versioning scheme is defined by the vendor. | -| `rd_uid` | rotating device ID unique ID | <16, 32> B | byte string | mandatory | The unique ID for rotating device ID, which consists of a randomly-generated 128-bit (or longer) octet string. This parameter should be protected against reading or writing over-the-air after initial introduction into the device, and stay fixed during the lifetime of the device. | -| `dac_cert` | (DAC) Device Attestation Certificate | <1, 602> B | byte string | mandatory | The Device Attestation Certificate (DAC) and the corresponding private key are unique to each Matter device. The DAC is used for the Device Attestation process and to perform commissioning into a fabric. The DAC is a DER-encoded X.509v3-compliant certificate, as defined in RFC 5280. | -| `dac_key` | DAC private key | 68 B | byte string | mandatory | The private key associated with the Device Attestation Certificate (DAC). This key should be encrypted and maximum security should be guaranteed while generating and providing it to factory data. | -| `pai_cert` | Product Attestation Intermediate | <1, 602> B | byte string | mandatory | An intermediate certificate is an X.509 certificate, which has been signed by the root certificate. The last intermediate certificate in a chain is used to sign the leaf (the Matter device) certificate. The PAI is a DER-encoded X.509v3-compliant certificate as defined in RFC 5280. | | -| `spake2_it` | SPAKE2+ iteration counter | 4 B | uint32 | mandatory | A SPAKE2+ iteration counter is the amount of PBKDF2 (a key derivation function) interactions in a cryptographic process used during SPAKE2+ Verifier generation. | -| `spake2_salt` | SPAKE2+ salt | <32, 64> B | byte string | mandatory | The SPAKE2+ salt is a random piece of data, at least 32 byte long. It is used as an additional input to a one-way function that performs the cryptographic operations. A new salt should be randomly generated for each password. | -| `spake2_verifier` | SPAKE2+ verifier | 97 B | byte string | mandatory | The SPAKE2+ verifier generated using SPAKE2+ salt, iteration counter, and passcode. | -| `discriminator` | Discriminator | 2 B | uint16 | mandatory | A 12-bit value matching the field of the same name in the setup code. The discriminator is used during the discovery process. | -| `passcode` | SPAKE passcode | 4 B | uint32 | optional | A pairing passcode is a 27-bit unsigned integer which serves as a proof of possession during the commissioning. Its value must be restricted to the values from `0x0000001` to `0x5F5E0FE` (`00000001` to `99999998` in decimal), excluding the following invalid passcode values: `00000000`, `11111111`, `22222222`, `33333333`, `44444444`, `55555555`, `66666666`, `77777777`, `88888888`, `99999999`, `12345678`, `87654321`. | -| `user` | User data | variable | JSON string | max 1024 B | The user data is provided in the JSON format. This parameter is optional and depends on device manufacturer's purpose. It is provided as a CBOR map type from persistent storage and should be parsed in the user application. This data is not used by the Matter stack. To learn how to work with user data, see [How to set user data](#how-to-set-user-data) section. | +| Key name | Full name | Length | Format | Conformance | Description | +| :------------------: | :----------------------------------: | :------------------: | :----------: | :---------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| `version` | factory data version | 2 B | uint16 | mandatory | A version of the current factory data set. It cannot be changed by a user and it must be coherent with current version of the Factory Data Provider on device side. | +| `sn` | serial number | <1, 32> B | ASCII string | mandatory | A serial number parameter defines an unique number of manufactured device. The maximum length of the serial number is 32 characters. | +| `vendor_id` | vendor ID | 2 B | uint16 | mandatory | A CSA-assigned ID for the organization responsible for producing the device. | +| `product_id` | product ID | 2 B | uint16 | mandatory | A unique ID assigned by the device vendor to identify the product. It defaults to a CSA-assigned ID that designates a non-production or test product. | +| `vendor_name` | vendor name | <1, 32> B | ASCII string | mandatory | A human-readable vendor name that provides a simple string containing identification of device's vendor for the application and Matter stack purposes. | +| `product_name` | product name | <1, 32> B | ASCII string | mandatory | A human-readable product name that provides a simple string containing identification of the product for the application and the Matter stack purposes. | +| `date` | manufacturing date | <8, 10> B | ISO 8601 | mandatory | A manufacturing date specifies the date that the device was manufactured. The date format used is ISO 8601, for example `YYYY-MM-DD`. | +| `hw_ver` | hardware version | 2 B | uint16 | mandatory | A hardware version number that specifies the version number of the hardware of the device. The value meaning and the versioning scheme is defined by the vendor. | +| `hw_ver_str` | hardware version string | <1, 64> B | uint16 | mandatory | A hardware version string parameter that specifies the version of the hardware of the device as a more user-friendly value than that presented by the hardware version integer value. The value meaning and the versioning scheme is defined by the vendor. | +| `rd_uid` | rotating device ID unique ID | <16, 32> B | byte string | mandatory | The unique ID for rotating device ID, which consists of a randomly-generated 128-bit (or longer) octet string. This parameter should be protected against reading or writing over-the-air after initial introduction into the device, and stay fixed during the lifetime of the device. | +| `dac_cert` | (DAC) Device Attestation Certificate | <1, 602> B | byte string | mandatory | The Device Attestation Certificate (DAC) and the corresponding private key are unique to each Matter device. The DAC is used for the Device Attestation process and to perform commissioning into a fabric. The DAC is a DER-encoded X.509v3-compliant certificate, as defined in RFC 5280. | +| `dac_key` | DAC private key | 68 B | byte string | mandatory | The private key associated with the Device Attestation Certificate (DAC). This key should be encrypted and maximum security should be guaranteed while generating and providing it to factory data. | +| `pai_cert` | Product Attestation Intermediate | <1, 602> B | byte string | mandatory | An intermediate certificate is an X.509 certificate, which has been signed by the root certificate. The last intermediate certificate in a chain is used to sign the leaf (the Matter device) certificate. The PAI is a DER-encoded X.509v3-compliant certificate as defined in RFC 5280. | | +| `spake2_it` | SPAKE2+ iteration counter | 4 B | uint32 | mandatory | A SPAKE2+ iteration counter is the amount of PBKDF2 (a key derivation function) interactions in a cryptographic process used during SPAKE2+ Verifier generation. | +| `spake2_salt` | SPAKE2+ salt | <32, 64> B | byte string | mandatory | The SPAKE2+ salt is a random piece of data, at least 32 byte long. It is used as an additional input to a one-way function that performs the cryptographic operations. A new salt should be randomly generated for each password. | +| `spake2_verifier` | SPAKE2+ verifier | 97 B | byte string | mandatory | The SPAKE2+ verifier generated using SPAKE2+ salt, iteration counter, and passcode. | +| `discriminator` | Discriminator | 2 B | uint16 | mandatory | A 12-bit value matching the field of the same name in the setup code. The discriminator is used during the discovery process. | +| `passcode` | SPAKE passcode | 4 B | uint32 | optional | A pairing passcode is a 27-bit unsigned integer which serves as a proof of possession during the commissioning. Its value must be restricted to the values from `0x0000001` to `0x5F5E0FE` (`00000001` to `99999998` in decimal), excluding the following invalid passcode values: `00000000`, `11111111`, `22222222`, `33333333`, `44444444`, `55555555`, `66666666`, `77777777`, `88888888`, `99999999`, `12345678`, `87654321`. | +| `product_appearance` | Product visible appearance | 2 B | CBOR map | optional | The appearance field is a structure that describes the visible appearance of the product. This field is provided in a CBOR map and consists of two attributes: `finish` (1 B), `primary_color` (1 B). See the [Appearance field description](#appearance-field-description) to learn how to set all attributes. | +| `user` | User data | variable, max 1024 B | CBOR map | optional | The user data is provided in the JSON format. This parameter is optional and depends on the device manufacturer's purpose. It is provided as a CBOR map type from persistent storage and should be parsed in the user application. This data is not used by the Matter stack. To learn how to work with user data, see the [How to set user data](#how-to-set-user-data) section. | ### Factory data format @@ -131,10 +134,10 @@ All parameters of the factory data set are either mandatory or optional: In the factory data set, the following formats are used: -- uint16 and uint32 -- These are the numeric formats representing, - respectively, two-bytes length unsigned integer and four-bytes length - unsigned integer. This value is stored in a HEX file in the big-endian - order. +- uint8, uint16, and uint32 -- These are the numeric formats representing, + respectively, one-byte length unsigned integer, two-bytes length unsigned + integer, and four-bytes length unsigned integer. This value is stored in a + HEX file in the big-endian order. - Byte string - This parameter represents the sequence of integers between `0` and `255`(inclusive), without any encoding. Because the JSON format does not allow to use of byte strings, the `hex:` prefix is added to a parameter, and @@ -150,6 +153,37 @@ In the factory data set, the following formats are used: - All certificates stored in factory data are provided in the [X.509](https://www.itu.int/rec/T-REC-X.509-201910-I/en) format. +#### Appearance field description + +The `appearance` field in the factory data set describes the device's visible +appearance. + +- `finish` - A string name that indicates the visible exterior finish of the + product. It refers to the `ProductFinishEnum` enum, and currently, you can + choose one of the following names: + +| Name | Enum value | +| :--------: | :--------: | +| `matte` | 0 | +| `satin` | 1 | +| `polished` | 2 | +| `rugged` | 3 | +| `fabric` | 4 | +| `other` | 255 | + +- `primary_color` - A string name that represents the RGB color space of the + device's case color, which is the most representative. It refers to the + `ColorEnum` enum, and currently, you can choose one of the following names: + +(Enum value) color name (`RGB value`) + +| (0) $$\color{black} \color{black}{black}$$ (`#000000`) | (1) $$\color{#000080}{navy}$$ (`#000080`) | (2) $$\color{#008000}{green}$$ (`#008000`) | (3) $$\color{#008080}{teal}$$ (`#008080`) | (4) $$\color{#800080}{maroon}$$ (`#800080`) | +| ------------------------------------------------------ | -------------------------------------------- | --------------------------------------------- | -------------------------------------------- | ------------------------------------------------------- | +| (5) $$\color{#800080}{purple}$$ (`#800080`) | (6) $$\color{#808000}{olive}$$ (`#800080`) | (7) $$\color{#808080}{gray}$$ (`#800080`) | (8) $$\color{blue}{blue}$$ (`#0000FF`) | (9) $$\color{lime}{lime}$$ (`#00FF00`) | +| (10) $$\color{aqua}{aqua}$$ (`#00FFFF`) | (11) $$\color{red}{red}$$ (`#FF0000`) | (12) $$\color{fuchsia}{fuchsia}$$ (`#FF00FF`) | (13) $$\color{yellow}{yellow}$$ (`#FFFF00`) | (14) $$\color{white} \color{white}{white}$$ (`#800080`) | +| (15) $$\color{#727472}{nickel}$$ (`#727472`) | (16) $$\color{#a8a9ad}{chrome}$$ (`#a8a9ad`) | (17) $$\color{#E1C16E}{brass}$$ (`#E1C16E`) | (18) $$\color{#B87333}{copper}$$ (`#B87333`) | (19) $$\color{#C0C0C0}{silver}$$ (`#C0C0C0`) | +| (20) $$\color{gold}{gold}$$ (`#FFD700`) | +
## Enabling factory data support @@ -287,6 +321,13 @@ To use this script, complete the following steps: --overwrite ``` + i. (optional) Add the appearance of the product: + + ``` + --product_finish + --product_color + ``` + 4. Run the script using the prepared list of arguments: ``` @@ -314,7 +355,9 @@ $ python scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py \ --discriminator 0xF00 \ --generate_rd_uid \ --passcode 20202021 \ ---out "build.json" \ +--product_finish "matte" \ +--product_color "black" \ +--out "build.json"' \ --schema "scripts/tools/nrfconnect/nrfconnect_factory_data.schema" ``` diff --git a/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py b/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py index 38e11967e744c1..c013bbbd1ffa5c 100644 --- a/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py +++ b/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py @@ -61,6 +61,10 @@ PUB_KEY_PREFIX = b'\x04' INVALID_PASSCODES = [00000000, 11111111, 22222222, 33333333, 44444444, 55555555, 66666666, 77777777, 88888888, 99999999, 12345678, 87654321] +PRODUCT_FINISH_ENUM = {"other": 0, "matte": 1, "satin": 2, "polished": 3, "rugged": 4, "fabric": 5} +PRODUCT_COLOR_ENUM = {"black": 0, "navy": 1, "green": 2, "teal": 3, "maroon": 4, "purple": 5, "olive": 6, "gray": 7, "blue": 8, "lime": 9, + "aqua": 10, "red": 11, "fuchsia": 12, "yellow": 13, "white": 14, "nickel": 15, "chrome": 16, "brass": 18, "cooper": 19, + "silver": 19, "gold": 20} sys.path.insert(0, os.path.join(MATTER_ROOT, 'scripts', 'tools', 'spake2p')) from spake2p import generate_verifier # noqa: E402 isort:skip @@ -325,6 +329,10 @@ def generate_json(self): self._add_entry("rd_uid", rd_uid) if self._args.enable_key: self._add_entry("enable_key", HEX_PREFIX + self._args.enable_key) + if self._args.product_finish: + self._add_entry("product_finish", PRODUCT_FINISH_ENUM[self._args.product_finish]) + if self._args.product_color: + self._add_entry("primary_color", PRODUCT_COLOR_ENUM[self._args.product_color]) if self._args.user: self._add_entry("user", self._user_data) @@ -516,6 +524,10 @@ def base64_str(s): return base64.b64decode(s) optional_arguments.add_argument("--generate_onboarding", action="store_true", help=("Generate a Manual Code and QR Code according to provided factory data set." "As a result a PNG image containing QRCode and a .txt file containing Manual Code will be available within output directory")) + optional_arguments.add_argument("--product_finish", type=str, choices=PRODUCT_FINISH_ENUM.keys(), + help="[string] Provide one of the product finishes") + optional_arguments.add_argument("--product_color", type=str, choices=PRODUCT_COLOR_ENUM.keys(), + help="[string] Provide one of the product colors.") args = parser.parse_args() if args.verbose: diff --git a/scripts/tools/nrfconnect/nrfconnect_factory_data.schema b/scripts/tools/nrfconnect/nrfconnect_factory_data.schema index 84cbef50df8a78..0c61d3330826c3 100644 --- a/scripts/tools/nrfconnect/nrfconnect_factory_data.schema +++ b/scripts/tools/nrfconnect/nrfconnect_factory_data.schema @@ -156,6 +156,16 @@ "minLength": 36, "maxLength": 36 }, + "product_finish": { + "description": "Product finish provides a description of the product's external case finish method (matte, satin, polished, rugged, fabric)", + "type": "integer", + "enum": [0, 1, 2, 3, 4, 5] + }, + "primary_color": { + "description": "Product finish provides a description of the product's primary color", + "type": "integer", + "enum": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] + }, "user": { "description": "A user-specific additional data which should be added to factory data. This should be a Json format.", "type": "object" diff --git a/scripts/tools/nrfconnect/tests/test_generate_factory_data.py b/scripts/tools/nrfconnect/tests/test_generate_factory_data.py index 0be21f8fcb8bad..3efe948be5c84b 100755 --- a/scripts/tools/nrfconnect/tests/test_generate_factory_data.py +++ b/scripts/tools/nrfconnect/tests/test_generate_factory_data.py @@ -177,6 +177,8 @@ def test_generate_factory_data_all_specified(self): '--discriminator', '0xFED', '--rd_uid', '91a9c12a7c80700a31ddcfa7fce63e44', '--enable_key', '00112233445566778899aabbccddeeff', + '--product_color', 'red', + '--product_finish', 'satin', '--user', '{"name": "product_name", "version": 123, "revision": "0x123"}', '-o', os.path.join(outdir, 'fd.json') ]) @@ -207,6 +209,8 @@ def test_generate_factory_data_all_specified(self): self.assertEqual(factory_data.get('passcode'), 13243546) self.assertEqual(factory_data.get('rd_uid'), 'hex:91a9c12a7c80700a31ddcfa7fce63e44') self.assertEqual(factory_data.get('enable_key'), 'hex:00112233445566778899aabbccddeeff') + self.assertEqual(factory_data.get('product_finish'), 2) + self.assertEqual(factory_data.get('primary_color'), 11) self.assertEqual(factory_data.get('user'), {'name': 'product_name', 'version': 123, 'revision': '0x123'}) subprocess.check_call(['python3', os.path.join(TOOLS_DIR, 'nrfconnect_generate_partition.py'), diff --git a/src/platform/nrfconnect/FactoryDataParser.c b/src/platform/nrfconnect/FactoryDataParser.c index 56da5343d973dc..45f9951f7ea8db 100644 --- a/src/platform/nrfconnect/FactoryDataParser.c +++ b/src/platform/nrfconnect/FactoryDataParser.c @@ -22,7 +22,7 @@ #include #include -#define MAX_FACTORY_DATA_NESTING_LEVEL 3 +#define MAX_FACTORY_DATA_NESTING_LEVEL 4 static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value) { @@ -37,6 +37,19 @@ static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value) return false; } +static inline bool uint8_decode(zcbor_state_t * states, uint8_t * value) +{ + uint32_t u32; + + if (zcbor_uint32_decode(states, &u32)) + { + *value = (uint8_t) u32; + return true; + } + + return false; +} + static bool DecodeEntry(zcbor_state_t * states, void * buffer, size_t bufferSize, size_t * outlen) { struct zcbor_string tempString; @@ -233,6 +246,16 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData { res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->enable_key); } + else if (strncmp("product_finish", (const char *) currentString.value, currentString.len) == 0) + { + res = res && uint8_decode(states, &factoryData->product_finish); + factoryData->productFinishPresent = res; + } + else if (strncmp("primary_color", (const char *) currentString.value, currentString.len) == 0) + { + res = res && uint8_decode(states, &factoryData->primary_color); + factoryData->primaryColorPresent = res; + } else if (strncmp("user", (const char *) currentString.value, currentString.len) == 0) { factoryData->user.data = (void *) states->payload; diff --git a/src/platform/nrfconnect/FactoryDataParser.h b/src/platform/nrfconnect/FactoryDataParser.h index b600371dde96ee..54be7b80b8a832 100644 --- a/src/platform/nrfconnect/FactoryDataParser.h +++ b/src/platform/nrfconnect/FactoryDataParser.h @@ -58,11 +58,14 @@ struct FactoryData uint32_t passcode; struct FactoryDataString enable_key; struct FactoryDataString user; - + uint8_t product_finish; + uint8_t primary_color; bool vendorIdPresent; bool productIdPresent; bool hwVerPresent; bool discriminatorPresent; + bool productFinishPresent; + bool primaryColorPresent; }; /** diff --git a/src/platform/nrfconnect/FactoryDataProvider.cpp b/src/platform/nrfconnect/FactoryDataProvider.cpp index 229eb2745d6c91..86fb8a354b9a5a 100644 --- a/src/platform/nrfconnect/FactoryDataProvider.cpp +++ b/src/platform/nrfconnect/FactoryDataProvider.cpp @@ -339,6 +339,27 @@ CHIP_ERROR FactoryDataProvider::GetEnableKey(MutableByteSpan & return CHIP_NO_ERROR; } +template +CHIP_ERROR FactoryDataProvider::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) +{ + ReturnErrorCodeIf(!finish, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(!mFactoryData.productFinishPresent, CHIP_ERROR_NOT_IMPLEMENTED); + *finish = static_cast(mFactoryData.product_finish); + + return CHIP_NO_ERROR; +} + +template +CHIP_ERROR FactoryDataProvider::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) +{ + ReturnErrorCodeIf(!primaryColor, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(!mFactoryData.primaryColorPresent, CHIP_ERROR_NOT_IMPLEMENTED); + + *primaryColor = static_cast(mFactoryData.primary_color); + + return CHIP_NO_ERROR; +} + template CHIP_ERROR FactoryDataProvider::GetUserData(MutableByteSpan & userData) { diff --git a/src/platform/nrfconnect/FactoryDataProvider.h b/src/platform/nrfconnect/FactoryDataProvider.h index c5517917cddde6..368ec957eff5bd 100644 --- a/src/platform/nrfconnect/FactoryDataProvider.h +++ b/src/platform/nrfconnect/FactoryDataProvider.h @@ -107,6 +107,8 @@ class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentia CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override; CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override; CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override; + CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override; + CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override; // ===== Members functions that are platform-specific CHIP_ERROR GetEnableKey(MutableByteSpan & enableKey);