diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml
index d9df0bca21637f..b0b4fef50e15df 100644
--- a/.github/workflows/examples-efr32.yaml
+++ b/.github/workflows/examples-efr32.yaml
@@ -41,7 +41,7 @@ jobs:
if: github.actor != 'restyled-io[bot]'
container:
- image: ghcr.io/project-chip/chip-build-efr32:84
+ image: ghcr.io/project-chip/chip-build-efr32:85
volumes:
- "/tmp/bloat_reports:/tmp/bloat_reports"
steps:
diff --git a/.github/workflows/release_artifacts.yaml b/.github/workflows/release_artifacts.yaml
index af90dc316d0f4a..54997b6efa9b39 100644
--- a/.github/workflows/release_artifacts.yaml
+++ b/.github/workflows/release_artifacts.yaml
@@ -64,7 +64,7 @@ jobs:
runs-on: ubuntu-latest
container:
- image: ghcr.io/project-chip/chip-build-efr32:84
+ image: ghcr.io/project-chip/chip-build-efr32:85
steps:
- name: Checkout
uses: actions/checkout@v4
diff --git a/.gitmodules b/.gitmodules
index 3f50d3079d4e03..c2b9a95a5e0345 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -213,7 +213,7 @@
[submodule "third_party/silabs/simplicity_sdk"]
path = third_party/silabs/simplicity_sdk
url = https://github.com/SiliconLabs/simplicity_sdk.git
- branch = v2024.6.1-0
+ branch = v2024.6.2
platforms = silabs
[submodule "third_party/silabs/wiseconnect-wifi-bt-sdk"]
path = third_party/silabs/wiseconnect-wifi-bt-sdk
diff --git a/docs/development_controllers/chip-tool/chip_tool_guide.md b/docs/development_controllers/chip-tool/chip_tool_guide.md
index 8aac8daa121812..81000368a47f0c 100644
--- a/docs/development_controllers/chip-tool/chip_tool_guide.md
+++ b/docs/development_controllers/chip-tool/chip_tool_guide.md
@@ -9,33 +9,29 @@ the setup payload or performing discovery actions.
-## Source files
+## Installation
-You can find source files of the CHIP Tool in the `examples/chip-tool`
-directory.
-
-> **Note:** The CHIP Tool caches the configuration state in the
-> `/tmp/chip_tool_config.ini` file. Deleting this and other `.ini` files in the
-> `/tmp` directory can sometimes resolve issues related to stale configuration.
+On Linux distributions
+[running snapd](https://snapcraft.io/docs/installing-snapd), such as Ubuntu, the
+CHIP Tool can be installed using the
+[chip-tool snap](https://snapcraft.io/chip-tool). To do this, run:
-> **Note:** To make the configuration persistent (since `/tmp` directory might
-> be flushed at each reboot) you can change the directory where CHIP Tool caches
-> its configuration by using the option `--storage-directory`
+```
+sudo snap install chip-tool
+```
-
+## Building from source
-## Building and running the CHIP Tool
+The source files of the CHIP Tool are available in the `examples/chip-tool`
+directory.
-Before you can use the CHIP Tool, you must compile it from source on Linux
-(amd64/aarch64) or macOS. If you want to run it on Raspberry Pi, it must use a
-64-bit OS.
+The source can be compiled on Linux (amd64/aarch64) or macOS. If you want to run
+it on Raspberry Pi, you must use a 64-bit OS.
> **Note:** To ensure compatibility, always build the CHIP Tool and the Matter
> device from the same revision of the `connectedhomeip` repository.
-### Building the CHIP Tool
-
-To build and run the CHIP Tool:
+To build the CHIP Tool:
1. Install all required packages for Matter and prepare the source code and the
build system. Read the [Building Matter](../../guides/BUILDING.md) guide for
@@ -50,10 +46,16 @@ To build and run the CHIP Tool:
In this command, `BUILD_PATH` specifies where the target binaries are to be
placed.
-### Running the CHIP Tool
+## Running the CHIP Tool
+
+If you installed the CHIP Tool as a snap, the command to run it would be:
+
+```
+$ chip-tool
+```
-To check if the CHIP Tool runs correctly, execute the following command from the
-`BUILD_PATH` directory:
+If you compiled the CHIP Tool from source, it can be executed with the following
+command from the `BUILD_PATH` directory:
```
$ ./chip-tool
@@ -68,6 +70,13 @@ more complex command by appending it with sub-commands. Examples of specific
commands and their use cases are described in the
[Supported commands and options](#supported-commands-and-options) section.
+> **Note:** The CHIP Tool caches the configuration state in the
+> `/tmp/chip_tool_config.ini` file. Deleting this and other `.ini` files in the
+> `/tmp` directory can sometimes resolve issues related to stale configuration.
+> To make the configuration persistent you can change the directory where CHIP
+> Tool caches its configuration by using the command line option
+> `--storage-directory`
+
## CHIP Tool modes
diff --git a/examples/light-switch-app/nrfconnect/README.md b/examples/light-switch-app/nrfconnect/README.md
index 11e53793463570..02f7b500aa6270 100644
--- a/examples/light-switch-app/nrfconnect/README.md
+++ b/examples/light-switch-app/nrfconnect/README.md
@@ -638,7 +638,7 @@ same Matter network.
To perform the unicast binding process, complete the following steps:
1. Build the CHIP Tool according to the steps from the
- [CHIP Tool user guide](../../../docs/development_controllers/chip-tool/chip_tool_guide.md#building-and-running-the-chip-tool).
+ [CHIP Tool user guide](../../../docs/development_controllers/chip-tool/chip_tool_guide.md#building-from-source).
2. Go to the CHIP Tool build directory.
3. Add an ACL to the development kit that is programmed with the
[Lighting Application Example](../../lighting-app/nrfconnect/README.md) by
@@ -690,7 +690,7 @@ same Matter network.
To perform the unicast binding process, complete the following steps:
1. Build the CHIP Tool according to the steps from the
- [CHIP Tool user guide](../../../docs/development_controllers/chip-tool/chip_tool_guide.md#building-and-running-the-chip-tool).
+ [CHIP Tool user guide](../../../docs/development_controllers/chip-tool/chip_tool_guide.md#building-from-source).
2. Go to the CHIP Tool build directory.
3. Add the light switch device to the multicast group by running the following
diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml
index 24a3029d2fe2f8..824b79d6ce1a22 100644
--- a/integrations/cloudbuild/smoke-test.yaml
+++ b/integrations/cloudbuild/smoke-test.yaml
@@ -1,5 +1,5 @@
steps:
- - name: "ghcr.io/project-chip/chip-build-vscode:84"
+ - name: "ghcr.io/project-chip/chip-build-vscode:85"
entrypoint: "bash"
args:
- "-c"
@@ -7,7 +7,7 @@ steps:
git config --global --add safe.directory "*"
python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android
id: Submodules
- - name: "ghcr.io/project-chip/chip-build-vscode:84"
+ - name: "ghcr.io/project-chip/chip-build-vscode:85"
# NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting
# jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3)
env:
@@ -24,7 +24,7 @@ steps:
path: /pwenv
timeout: 900s
- - name: "ghcr.io/project-chip/chip-build-vscode:84"
+ - name: "ghcr.io/project-chip/chip-build-vscode:85"
id: ESP32
env:
- PW_ENVIRONMENT_ROOT=/pwenv
@@ -45,7 +45,7 @@ steps:
volumes:
- name: pwenv
path: /pwenv
- - name: "ghcr.io/project-chip/chip-build-vscode:84"
+ - name: "ghcr.io/project-chip/chip-build-vscode:85"
id: NRFConnect
env:
- PW_ENVIRONMENT_ROOT=/pwenv
@@ -66,7 +66,7 @@ steps:
- name: pwenv
path: /pwenv
- - name: "ghcr.io/project-chip/chip-build-vscode:84"
+ - name: "ghcr.io/project-chip/chip-build-vscode:85"
id: EFR32
env:
- PW_ENVIRONMENT_ROOT=/pwenv
@@ -88,7 +88,7 @@ steps:
- name: pwenv
path: /pwenv
- - name: "ghcr.io/project-chip/chip-build-vscode:84"
+ - name: "ghcr.io/project-chip/chip-build-vscode:85"
id: Linux
env:
- PW_ENVIRONMENT_ROOT=/pwenv
@@ -141,7 +141,7 @@ steps:
- name: pwenv
path: /pwenv
- - name: "ghcr.io/project-chip/chip-build-vscode:84"
+ - name: "ghcr.io/project-chip/chip-build-vscode:85"
id: Android
env:
- PW_ENVIRONMENT_ROOT=/pwenv
diff --git a/src/app/clusters/thermostat-server/thermostat-server-presets.cpp b/src/app/clusters/thermostat-server/thermostat-server-presets.cpp
index 9413513fd0cedd..1dede071619962 100644
--- a/src/app/clusters/thermostat-server/thermostat-server-presets.cpp
+++ b/src/app/clusters/thermostat-server/thermostat-server-presets.cpp
@@ -152,69 +152,36 @@ bool GetMatchingPresetInPresets(Delegate * delegate, const DataModel::NullableGetPendingPresetAtIndex(i, pendingPreset);
-
+ PresetTypeStruct::Type presetType;
+ auto err = delegate->GetPresetTypeAtIndex(i, presetType);
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
{
- break;
+ // We exhausted the list trying to find the preset scenario
+ return CHIP_NO_ERROR;
}
if (err != CHIP_NO_ERROR)
{
- ChipLogError(Zcl, "CountNumberOfPendingPresets: GetPendingPresetAtIndex failed with error %" CHIP_ERROR_FORMAT,
- err.Format());
- return 0;
+ return err;
}
- numberOfPendingPresets++;
- }
-
- return numberOfPendingPresets;
-}
-
-/**
- * @brief Checks if the presetScenario is present in the PresetTypes attribute.
- *
- * @param[in] delegate The delegate to use.
- * @param[in] presetScenario The presetScenario to match with.
- *
- * @return true if the presetScenario is found, false otherwise.
- */
-bool PresetScenarioExistsInPresetTypes(Delegate * delegate, PresetScenarioEnum presetScenario)
-{
- VerifyOrReturnValue(delegate != nullptr, false);
-
- for (uint8_t i = 0; true; i++)
- {
- PresetTypeStruct::Type presetType;
- auto err = delegate->GetPresetTypeAtIndex(i, presetType);
- if (err != CHIP_NO_ERROR)
- {
- return false;
- }
-
if (presetType.presetScenario == presetScenario)
{
- return true;
+ count = presetType.numberOfPresets;
+ return CHIP_NO_ERROR;
}
}
- return false;
+ return CHIP_NO_ERROR;
}
/**
@@ -410,8 +377,16 @@ CHIP_ERROR ThermostatAttrAccess::AppendPendingPreset(Thermostat::Delegate * dele
}
}
- if (!PresetScenarioExistsInPresetTypes(delegate, preset.GetPresetScenario()))
+ size_t maximumPresetCount = delegate->GetNumberOfPresets();
+ size_t maximumPresetScenarioCount = 0;
+ if (MaximumPresetScenarioCount(delegate, preset.GetPresetScenario(), maximumPresetScenarioCount) != CHIP_NO_ERROR)
{
+ return CHIP_IM_GLOBAL_STATUS(InvalidInState);
+ }
+
+ if (maximumPresetScenarioCount == 0)
+ {
+ // This is not a supported preset scenario
return CHIP_IM_GLOBAL_STATUS(ConstraintError);
}
@@ -423,16 +398,42 @@ CHIP_ERROR ThermostatAttrAccess::AppendPendingPreset(Thermostat::Delegate * dele
// Before adding this preset to the pending presets, if the expected length of the pending presets' list
// exceeds the total number of presets supported, return RESOURCE_EXHAUSTED. Note that the preset has not been appended yet.
- uint8_t numberOfPendingPresets = CountNumberOfPendingPresets(delegate);
+ // We're going to append this preset, so let's assume a count as though it had already been inserted
+ size_t presetCount = 1;
+ size_t presetScenarioCount = 1;
+ for (uint8_t i = 0; true; i++)
+ {
+ PresetStructWithOwnedMembers otherPreset;
+ CHIP_ERROR err = delegate->GetPendingPresetAtIndex(i, otherPreset);
+
+ if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
+ {
+ break;
+ }
+ if (err != CHIP_NO_ERROR)
+ {
+ return CHIP_IM_GLOBAL_STATUS(InvalidInState);
+ }
+ presetCount++;
+ if (preset.GetPresetScenario() == otherPreset.GetPresetScenario())
+ {
+ presetScenarioCount++;
+ }
+ }
- // We will be adding one more preset, so reject if the length is already at max.
- if (numberOfPendingPresets >= delegate->GetNumberOfPresets())
+ if (presetCount > maximumPresetCount)
{
+ ChipLogError(Zcl, "Preset count exceeded %u: %u ", static_cast(maximumPresetCount),
+ static_cast(presetCount));
return CHIP_IM_GLOBAL_STATUS(ResourceExhausted);
}
- // TODO #34556 : Check if the number of presets for each presetScenario exceeds the max number of presets supported for that
- // scenario. We plan to support only one preset for each presetScenario for our use cases so defer this for re-evaluation.
+ if (presetScenarioCount > maximumPresetScenarioCount)
+ {
+ ChipLogError(Zcl, "Preset scenario count exceeded %u: %u ", static_cast(maximumPresetScenarioCount),
+ static_cast(presetScenarioCount));
+ return CHIP_IM_GLOBAL_STATUS(ResourceExhausted);
+ }
return delegate->AppendToPendingPresetList(preset);
}
diff --git a/src/app/tests/suites/certification/Test_TC_LVL_2_1.yaml b/src/app/tests/suites/certification/Test_TC_LVL_2_1.yaml
index 8e9ee05b33e9ff..aa0fbcfddc83bf 100644
--- a/src/app/tests/suites/certification/Test_TC_LVL_2_1.yaml
+++ b/src/app/tests/suites/certification/Test_TC_LVL_2_1.yaml
@@ -188,6 +188,16 @@ tests:
minValue: MinLevelFeatureMapNotSupportedValue
maxValue: MaxLevelFeatureMapNotSupportedValue
+ - label: "Step 9c: TH reads the OnLevel attribute from the DUT"
+ PICS: LVL.S.A0011 && !LVL.S.F01 && !LVL.S.A0002 && !LVL.S.A0003
+ command: "readAttribute"
+ attribute: "OnLevel"
+ response:
+ constraints:
+ type: int8u
+ minValue: 0
+ maxValue: 254
+
- label: "Step 10: TH reads the OnTransitionTime attribute from the DUT"
PICS: LVL.S.A0012
command: "readAttribute"
diff --git a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml
index f7f5699ef8fccf..ff485bbf6bba81 100644
--- a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml
+++ b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml
@@ -2698,4 +2698,47 @@ limitations under the License.
+
+ MA-waterheater
+ CHIP
+ Water Heater
+ 0x0103
+ 0x050F
+ Simple
+ Endpoint
+
+
+ CLIENT_LIST
+ DEVICE_TYPE_LIST
+ PARTS_LIST
+ SERVER_LIST
+
+
+ IDENTIFY_TIME
+ IDENTIFY_TYPE
+ Identify
+
+
+ CONTROL_SEQUENCE_OF_OPERATION
+ LOCAL_TEMPERATURE
+ SYSTEM_MODE
+ SetpointRaiseLower
+
+
+ BOOST_STATE
+ HEATER_TYPES
+ HEAT_DEMAND
+ BoostEnded
+ BoostStarted
+ Boost
+ CancelBoost
+
+
+ CURRENT_MODE
+ SUPPORTED_MODES
+ ChangeToMode
+ ChangeToModeResponse
+
+
+
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
index b1d26e9ce0fb12..da2ce72f59373d 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
@@ -7625,6 +7625,7 @@ typedef NS_ENUM(uint32_t, MTRDeviceTypeIDType) {
MTRDeviceTypeIDTypeHumiditySensorID MTR_NEWLY_AVAILABLE = 0x00000307,
MTRDeviceTypeIDTypeEVSEID MTR_NEWLY_AVAILABLE = 0x0000050C,
MTRDeviceTypeIDTypeDeviceEnergyManagementID MTR_NEWLY_AVAILABLE = 0x0000050D,
+ MTRDeviceTypeIDTypeWaterHeaterID MTR_PROVISIONALLY_AVAILABLE = 0x0000050F,
MTRDeviceTypeIDTypeElectricalSensorID MTR_NEWLY_AVAILABLE = 0x00000510,
MTRDeviceTypeIDTypeControlBridgeID MTR_NEWLY_AVAILABLE = 0x00000840,
MTRDeviceTypeIDTypeOnOffSensorID MTR_NEWLY_AVAILABLE = 0x00000850,
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRDeviceTypeMetadata.mm b/src/darwin/Framework/CHIP/zap-generated/MTRDeviceTypeMetadata.mm
index f0530c41a54f00..b4ea67c2ed66fe 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRDeviceTypeMetadata.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRDeviceTypeMetadata.mm
@@ -85,6 +85,7 @@
{ 0x00000307, MTRDeviceTypeClass::Simple, "Humidity Sensor" },
{ 0x0000050C, MTRDeviceTypeClass::Simple, "EVSE" },
{ 0x0000050D, MTRDeviceTypeClass::Simple, "Device Energy Management" },
+ { 0x0000050F, MTRDeviceTypeClass::Simple, "Water Heater" },
{ 0x00000510, MTRDeviceTypeClass::Utility, "Electrical Sensor" },
{ 0x00000840, MTRDeviceTypeClass::Simple, "Control Bridge" },
{ 0x00000850, MTRDeviceTypeClass::Simple, "On/Off Sensor" },
diff --git a/src/lib/support/BufferReader.cpp b/src/lib/support/BufferReader.cpp
index 02bce8f3fe0615..cbd13f1ed172dc 100644
--- a/src/lib/support/BufferReader.cpp
+++ b/src/lib/support/BufferReader.cpp
@@ -18,12 +18,29 @@
#include "BufferReader.h"
#include
+#include
+#include
#include
#include
namespace chip {
namespace Encoding {
+
+BufferReader & BufferReader::ReadBytes(uint8_t * dest, size_t size)
+{
+ static_assert(CHAR_BIT == 8, "Our various sizeof checks rely on bytes and octets being the same thing");
+
+ if (EnsureAvailable(size))
+ {
+ memcpy(dest, mReadPtr, size);
+ mReadPtr += size;
+ mAvailable -= size;
+ }
+
+ return *this;
+}
+
namespace LittleEndian {
namespace {
@@ -58,37 +75,12 @@ void Reader::RawReadLowLevelBeCareful(T * retval)
constexpr size_t data_size = sizeof(T);
- if (mAvailable < data_size)
- {
- mStatus = CHIP_ERROR_BUFFER_TOO_SMALL;
- // Ensure that future reads all fail.
- mAvailable = 0;
- return;
- }
-
- ReadHelper(mReadPtr, retval);
- mReadPtr += data_size;
-
- mAvailable = static_cast(mAvailable - data_size);
-}
-
-Reader & Reader::ReadBytes(uint8_t * dest, size_t size)
-{
- static_assert(CHAR_BIT == 8, "Our various sizeof checks rely on bytes and octets being the same thing");
-
- if ((size > UINT16_MAX) || (mAvailable < size))
+ if (EnsureAvailable(data_size))
{
- mStatus = CHIP_ERROR_BUFFER_TOO_SMALL;
- // Ensure that future reads all fail.
- mAvailable = 0;
- return *this;
+ ReadHelper(mReadPtr, retval);
+ mReadPtr += data_size;
+ mAvailable -= data_size;
}
-
- memcpy(dest, mReadPtr, size);
-
- mReadPtr += size;
- mAvailable = static_cast(mAvailable - size);
- return *this;
}
// Explicit Read instantiations for the data types we want to support.
@@ -104,5 +96,46 @@ template void Reader::RawReadLowLevelBeCareful(uint32_t *);
template void Reader::RawReadLowLevelBeCareful(uint64_t *);
} // namespace LittleEndian
+
+namespace BigEndian {
+
+Reader & Reader::Read16(uint16_t * dest)
+{
+ if (!EnsureAvailable(sizeof(uint16_t)))
+ {
+ return *this;
+ }
+
+ static_assert(sizeof(*dest) == 2);
+
+ *dest = static_cast((mReadPtr[0] << 8) + mReadPtr[1]);
+ mReadPtr += 2;
+ mAvailable -= 2;
+ return *this;
+}
+
+Reader & Reader::Read32(uint32_t * dest)
+{
+ if (!EnsureAvailable(sizeof(uint32_t)))
+ {
+ return *this;
+ }
+
+ static_assert(sizeof(*dest) == 4);
+
+ *dest = 0;
+ for (unsigned i = 0; i < sizeof(uint32_t); i++)
+ {
+ *dest <<= 8;
+ *dest += mReadPtr[i];
+ }
+
+ mReadPtr += sizeof(uint32_t);
+ mAvailable -= sizeof(uint32_t);
+ return *this;
+}
+
+} // namespace BigEndian
+
} // namespace Encoding
} // namespace chip
diff --git a/src/lib/support/BufferReader.h b/src/lib/support/BufferReader.h
index ac9c7145359335..725ca8e23ea915 100644
--- a/src/lib/support/BufferReader.h
+++ b/src/lib/support/BufferReader.h
@@ -31,26 +31,11 @@
namespace chip {
namespace Encoding {
-namespace LittleEndian {
-/**
- * @class Reader
- *
- * Simple reader for reading little-endian things out of buffers.
- */
-class Reader
+class BufferReader
{
public:
- /**
- * Create a buffer reader from a given buffer and length.
- *
- * @param buffer The octet buffer from which to read. The caller must ensure
- * (most simply by allocating the reader on the stack) that
- * the buffer outlives the reader. If `buffer` is nullptr,
- * length is automatically overridden to zero, to avoid accesses.
- * @param buf_len The number of octets in the buffer.
- */
- Reader(const uint8_t * buffer, size_t buf_len) : mBufStart(buffer), mReadPtr(buffer), mAvailable(buf_len)
+ BufferReader(const uint8_t * buffer, size_t buf_len) : mBufStart(buffer), mReadPtr(buffer), mAvailable(buf_len)
{
if (mBufStart == nullptr)
{
@@ -58,15 +43,6 @@ class Reader
}
}
- /**
- * Create a buffer reader from a given byte span.
- *
- * @param buffer The octet buffer byte span from which to read. The caller must ensure
- * that the buffer outlives the reader. The buffer's ByteSpan .data() pointer
- * is is nullptr, length is automatically overridden to zero, to avoid accesses.
- */
- Reader(const ByteSpan & buffer) : Reader(buffer.data(), buffer.size()) {}
-
/**
* Number of octets we have read so far.
*/
@@ -95,6 +71,121 @@ class Reader
*/
bool IsSuccess() const { return StatusCode() == CHIP_NO_ERROR; }
+ /**
+ * Read a byte string from the BufferReader
+ *
+ * @param [out] dest Where the bytes read
+ * @param [in] size How many bytes to read
+ *
+ * @note The read can put the reader in a failed-status state if there are
+ * not enough octets available. Callers must either continue to do
+ * more reads on the return value or check its status to see whether
+ * the sequence of reads that has been performed succeeded.
+ */
+ CHECK_RETURN_VALUE
+ BufferReader & ReadBytes(uint8_t * dest, size_t size);
+
+ /**
+ * Access bytes of size length, useful for in-place processing of strings
+ *
+ * data_ptr MUST NOT be null and will contain the data pointer with `len` bytes available
+ * if this call is successful
+ *
+ * If len is greater than the number of available bytes, the object enters in a failed status.
+ */
+ CHECK_RETURN_VALUE
+ BufferReader & ZeroCopyProcessBytes(size_t len, const uint8_t ** data_ptr)
+ {
+ if (len > mAvailable)
+ {
+ *data_ptr = nullptr;
+ mStatus = CHIP_ERROR_BUFFER_TOO_SMALL;
+ // Ensure that future reads all fail.
+ mAvailable = 0;
+ }
+ else
+ {
+ *data_ptr = mReadPtr;
+ mReadPtr += len;
+ mAvailable -= len;
+ }
+ return *this;
+ }
+
+ /**
+ * Advance the Reader forward by the specified number of octets.
+ *
+ * @param len The number of octets to skip.
+ *
+ * @note If the len argument is greater than the number of available octets
+ * remaining, the Reader will advance to the end of the buffer
+ * without entering a failed-status state.
+ */
+ BufferReader & Skip(size_t len)
+ {
+ len = std::min(len, mAvailable);
+ mReadPtr += len;
+ mAvailable = static_cast(mAvailable - len);
+ return *this;
+ }
+
+protected:
+ /// Our buffer start.
+ const uint8_t * const mBufStart;
+
+ /// Our current read point.
+ const uint8_t * mReadPtr;
+
+ /// The number of octets we can still read starting at mReadPtr.
+ size_t mAvailable;
+
+ /// Our current status.
+ CHIP_ERROR mStatus = CHIP_NO_ERROR;
+
+ /// Make sure we have at least the given number of bytes available (does not consume them)
+ bool EnsureAvailable(size_t size)
+ {
+ if (mAvailable < size)
+ {
+ mStatus = CHIP_ERROR_BUFFER_TOO_SMALL;
+ // Ensure that future reads all fail.
+ mAvailable = 0;
+ return false;
+ }
+ return true;
+ }
+};
+
+namespace LittleEndian {
+
+/**
+ * @class Reader
+ *
+ * Simple reader for reading little-endian things out of buffers.
+ */
+class Reader : public BufferReader
+{
+public:
+ /**
+ * Create a buffer reader from a given buffer and length.
+ *
+ * @param buffer The octet buffer from which to read. The caller must ensure
+ * (most simply by allocating the reader on the stack) that
+ * the buffer outlives the reader. If `buffer` is nullptr,
+ * length is automatically overridden to zero, to avoid accesses.
+ * @param buf_len The number of octets in the buffer.
+ */
+ Reader(const uint8_t * buffer, size_t buf_len) : BufferReader(buffer, buf_len) {}
+
+ /**
+ * Create a buffer reader from a given byte span.
+ *
+ * @param buffer The octet buffer byte span from which to read. The caller must ensure
+ * that the buffer outlives the reader. The buffer's ByteSpan .data() pointer
+ * is is nullptr, length is automatically overridden to zero, to avoid accesses.
+ */
+ Reader(const ByteSpan & buffer) : Reader(buffer.data(), buffer.size()) {}
+
/**
* Read a bool, assuming single byte storage.
*
@@ -267,20 +358,6 @@ class Reader
return *this;
}
- /**
- * Read a byte string from the BufferReader
- *
- * @param [out] dest Where the bytes read
- * @param [in] size How many bytes to read
- *
- * @note The read can put the reader in a failed-status state if there are
- * not enough octets available. Callers must either continue to do
- * more reads on the return value or check its status to see whether
- * the sequence of reads that has been performed succeeded.
- */
- CHECK_RETURN_VALUE
- Reader & ReadBytes(uint8_t * dest, size_t size);
-
/**
* Helper for our various APIs so we don't have to write out various logic
* multiple times. This is public so that consumers that want to read into
@@ -290,46 +367,80 @@ class Reader
*/
template
void RawReadLowLevelBeCareful(T * retval);
+};
+
+} // namespace LittleEndian
+namespace BigEndian {
+
+/**
+ * @class Reader
+ *
+ * Simple reader for reading big-endian things out of buffers.
+ */
+class Reader : public BufferReader
+{
+public:
/**
- * Advance the Reader forward by the specified number of octets.
- *
- * @param len The number of octets to skip.
+ * Create a buffer reader from a given buffer and length.
*
- * @note If the len argument is greater than the number of available octets
- * remaining, the Reader will advance to the end of the buffer
- * without entering a failed-status state.
+ * @param buffer The octet buffer from which to read. The caller must ensure
+ * (most simply by allocating the reader on the stack) that
+ * the buffer outlives the reader. If `buffer` is nullptr,
+ * length is automatically overridden to zero, to avoid accesses.
+ * @param buf_len The number of octets in the buffer.
*/
- Reader & Skip(size_t len)
- {
- len = std::min(len, mAvailable);
- mReadPtr += len;
- mAvailable = static_cast(mAvailable - len);
- return *this;
- }
+ Reader(const uint8_t * buffer, size_t buf_len) : BufferReader(buffer, buf_len) {}
-private:
/**
- * Our buffer start.
+ * Create a buffer reader from a given byte span.
+ *
+ * @param buffer The octet buffer byte span from which to read. The caller must ensure
+ * that the buffer outlives the reader. If the buffer's ByteSpan .data() pointer
+ * is nullptr, length is automatically overridden to zero, to avoid accesses.
*/
- const uint8_t * const mBufStart;
+ Reader(const ByteSpan & buffer) : Reader(buffer.data(), buffer.size()) {}
/**
- * Our current read point.
+ * Read a single 8-bit unsigned integer.
+ *
+ * @param [out] dest Where the 8-bit integer goes.
+ *
+ * @note The read can put the reader in a failed-status state if there are
+ * not enough octets available. Callers must either continue to do
+ * more reads on the return value or check its status to see whether
+ * the sequence of reads that has been performed succeeded.
*/
- const uint8_t * mReadPtr;
+ CHECK_RETURN_VALUE
+ Reader & Read8(uint8_t * dest)
+ {
+ (void) ReadBytes(dest, 1);
+ return *this;
+ }
- /**
- * The number of octets we can still read starting at mReadPtr.
- */
- size_t mAvailable;
+ CHECK_RETURN_VALUE
+ Reader & ReadChar(char * dest)
+ {
+ (void) ReadBytes(reinterpret_cast(dest), 1);
+ return *this;
+ }
- /**
- * Our current status.
- */
- CHIP_ERROR mStatus = CHIP_NO_ERROR;
+ CHECK_RETURN_VALUE
+ Reader & ReadBool(char * dest)
+ {
+ (void) ReadBytes(reinterpret_cast(dest), 1);
+ return *this;
+ }
+
+ /// NOTE: only a subset of reads are supported here, more can be added if used/needed
+ CHECK_RETURN_VALUE
+ Reader & Read16(uint16_t * dest);
+
+ CHECK_RETURN_VALUE
+ Reader & Read32(uint32_t * dest);
};
-} // namespace LittleEndian
+} // namespace BigEndian
+
} // namespace Encoding
} // namespace chip
diff --git a/src/lib/support/tests/TestBufferReader.cpp b/src/lib/support/tests/TestBufferReader.cpp
index 97db9cf09737b9..ee100e1506bada 100644
--- a/src/lib/support/tests/TestBufferReader.cpp
+++ b/src/lib/support/tests/TestBufferReader.cpp
@@ -30,21 +30,21 @@
#include
using namespace chip;
-using namespace chip::Encoding::LittleEndian;
+using namespace chip::Encoding;
static const uint8_t test_buffer[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
-struct TestReader : public Reader
+struct LittleEndianTestReader : public LittleEndian::Reader
{
- TestReader() : Reader(test_buffer, std::extent::value) {}
+ LittleEndianTestReader() : LittleEndian::Reader(test_buffer, std::extent::value) {}
};
-struct TestSpanReader : public Reader
+struct LittleEndianTestSpanReader : public LittleEndian::Reader
{
- TestSpanReader() : Reader(ByteSpan{ test_buffer, std::extent::value }) {}
+ LittleEndianTestSpanReader() : LittleEndian::Reader(ByteSpan{ test_buffer, std::extent::value }) {}
};
-static void TestBufferReader_BasicImpl(Reader & reader)
+static void TestBufferReader_BasicImpl(LittleEndian::Reader & reader)
{
uint8_t first;
uint16_t second;
@@ -75,21 +75,21 @@ static void TestBufferReader_BasicImpl(Reader & reader)
TEST(TestBufferReader, TestBufferReader_Basic)
{
- TestReader reader;
+ LittleEndianTestReader reader;
TestBufferReader_BasicImpl(reader);
}
TEST(TestBufferReader, TestBufferReader_BasicSpan)
{
- TestSpanReader reader;
+ LittleEndianTestSpanReader reader;
TestBufferReader_BasicImpl(reader);
}
TEST(TestBufferReader, TestBufferReader_Saturation)
{
- TestReader reader;
+ LittleEndianTestReader reader;
uint64_t temp;
// Read some bytes out so we can get to the end of the buffer.
CHIP_ERROR err = reader.Read64(&temp).StatusCode();
@@ -113,12 +113,13 @@ TEST(TestBufferReader, TestBufferReader_Saturation)
TEST(TestBufferReader, TestBufferReader_Skip)
{
- TestReader reader;
+ LittleEndianTestReader reader;
uint8_t temp = 0;
uint16_t firstSkipLen = 2;
// Verify Skip() advances the start pointer the correct amount.
- CHIP_ERROR err = reader.Skip(firstSkipLen).Read8(&temp).StatusCode();
+ reader.Skip(firstSkipLen);
+ CHIP_ERROR err = reader.Read8(&temp).StatusCode();
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(temp, test_buffer[firstSkipLen]);
EXPECT_EQ(reader.OctetsRead(), (firstSkipLen + 1u));
@@ -175,7 +176,8 @@ TEST(TestBufferReader, TestBufferReader_LittleEndianScalars)
uint32_t val1 = 0;
uint32_t val2 = 0;
- EXPECT_TRUE(reader.Skip(1).Read32(&val1).Read32(&val2).IsSuccess());
+ reader.Skip(1);
+ EXPECT_TRUE(reader.Read32(&val1).Read32(&val2).IsSuccess());
EXPECT_EQ(reader.Remaining(), 1u);
EXPECT_EQ(val1, static_cast(0xfffffffeUL));
EXPECT_EQ(val2, static_cast(0xffffffffUL));
@@ -227,7 +229,8 @@ TEST(TestBufferReader, TestBufferReader_LittleEndianScalars)
int32_t val1 = 0;
int32_t val2 = 0;
- EXPECT_TRUE(reader.Skip(1).ReadSigned32(&val1).ReadSigned32(&val2).IsSuccess());
+ reader.Skip(1);
+ EXPECT_TRUE(reader.ReadSigned32(&val1).ReadSigned32(&val2).IsSuccess());
EXPECT_EQ(reader.Remaining(), 1u);
EXPECT_EQ(val1, static_cast(-2L));
EXPECT_EQ(val2, static_cast(-1L));
@@ -272,3 +275,23 @@ TEST(TestBufferReader, TestBufferReader_LittleEndianScalars)
EXPECT_EQ(val3, '\xff');
}
}
+
+TEST(TestBigEndianBufferReader, GenericTests)
+{
+ uint8_t test_buf[] = { 0x12, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xBC, 1, 2, 3 };
+
+ chip::Encoding::BigEndian::Reader reader{ ByteSpan{ test_buf } };
+
+ uint16_t v1;
+ uint32_t v2;
+ uint8_t v3;
+
+ EXPECT_TRUE(reader.Read16(&v1).Read32(&v2).Read8(&v3).IsSuccess());
+ EXPECT_EQ(reader.Remaining(), 3u);
+ EXPECT_EQ(v1, 0x1223u);
+ EXPECT_EQ(v2, 0x456789ABu);
+ EXPECT_EQ(v3, 0xBCu);
+
+ // Insufficient buffer after that
+ EXPECT_FALSE(reader.Read32(&v2).IsSuccess());
+}
diff --git a/src/platform/silabs/BLEManagerImpl.h b/src/platform/silabs/BLEManagerImpl.h
index 6d901db16e95db..9380accce38e55 100644
--- a/src/platform/silabs/BLEManagerImpl.h
+++ b/src/platform/silabs/BLEManagerImpl.h
@@ -58,12 +58,12 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla
#if (SLI_SI91X_ENABLE_BLE || RSI_BLE_ENABLE)
// Used for posting the event in the BLE queue
void BlePostEvent(SilabsBleWrapper::BleEvent_t * event);
- void HandleConnectEvent(SilabsBleWrapper::sl_wfx_msg_t * evt);
- void HandleConnectionCloseEvent(SilabsBleWrapper::sl_wfx_msg_t * evt);
- void HandleWriteEvent(SilabsBleWrapper::sl_wfx_msg_t * evt);
- void UpdateMtu(SilabsBleWrapper::sl_wfx_msg_t * evt);
+ void HandleConnectEvent(const SilabsBleWrapper::sl_wfx_msg_t & evt);
+ void HandleConnectionCloseEvent(const SilabsBleWrapper::sl_wfx_msg_t & evt);
+ void HandleWriteEvent(const SilabsBleWrapper::sl_wfx_msg_t & evt);
+ void UpdateMtu(const SilabsBleWrapper::sl_wfx_msg_t & evt);
void HandleTxConfirmationEvent(BLE_CONNECTION_OBJECT conId);
- void HandleTXCharCCCDWrite(SilabsBleWrapper::sl_wfx_msg_t * evt);
+ void HandleTXCharCCCDWrite(const SilabsBleWrapper::sl_wfx_msg_t & evt);
void HandleSoftTimerEvent(void);
int32_t SendBLEAdvertisementCommand(void);
#else
@@ -194,7 +194,7 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla
#endif
#if (SLI_SI91X_ENABLE_BLE || RSI_BLE_ENABLE)
- void HandleRXCharWrite(SilabsBleWrapper::sl_wfx_msg_t * evt);
+ void HandleRXCharWrite(const SilabsBleWrapper::sl_wfx_msg_t & evt);
#else
void HandleRXCharWrite(volatile sl_bt_msg_t * evt);
#endif
diff --git a/src/platform/silabs/rs911x/BLEManagerImpl.cpp b/src/platform/silabs/rs911x/BLEManagerImpl.cpp
index 44b2a17199b330..176f396f44cd1f 100644
--- a/src/platform/silabs/rs911x/BLEManagerImpl.cpp
+++ b/src/platform/silabs/rs911x/BLEManagerImpl.cpp
@@ -57,24 +57,7 @@ extern "C" {
#define BLE_TIMEOUT_MS 400
#define BLE_SEND_INDICATION_TIMER_PERIOD_MS (5000)
-// Used to send the Indication Confirmation
-uint8_t dev_address[RSI_DEV_ADDR_LEN];
-uint16_t ble_measurement_hndl;
-
osSemaphoreId_t sl_rs_ble_init_sem;
-osTimerId_t sbleAdvTimeoutTimer;
-
-static osThreadId_t sBleThread;
-constexpr uint32_t kBleTaskSize = 2048;
-static uint8_t bleStack[kBleTaskSize];
-static osThread_t sBleTaskControlBlock;
-constexpr osThreadAttr_t kBleTaskAttr = { .name = "rsi_ble",
- .attr_bits = osThreadDetached,
- .cb_mem = &sBleTaskControlBlock,
- .cb_size = osThreadCbSize,
- .stack_mem = bleStack,
- .stack_size = kBleTaskSize,
- .priority = osPriorityHigh };
using namespace ::chip;
using namespace ::chip::Ble;
@@ -111,6 +94,84 @@ const uint8_t UUID_CHIPoBLEService[] = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00
0x00, 0x10, 0x00, 0x00, 0xF6, 0xFF, 0x00, 0x00 };
const uint8_t ShortUUID_CHIPoBLEService[] = { 0xF6, 0xFF };
+// Used to send the Indication Confirmation
+uint8_t dev_address[RSI_DEV_ADDR_LEN];
+uint16_t rsi_ble_measurement_hndl;
+uint16_t rsi_ble_gatt_server_client_config_hndl;
+
+osTimerId_t sbleAdvTimeoutTimer;
+
+osThreadId_t sBleThread;
+constexpr uint32_t kBleTaskSize = 2560;
+uint8_t bleStack[kBleTaskSize];
+osThread_t sBleTaskControlBlock;
+constexpr osThreadAttr_t kBleTaskAttr = { .name = "rsi_ble",
+ .attr_bits = osThreadDetached,
+ .cb_mem = &sBleTaskControlBlock,
+ .cb_size = osThreadCbSize,
+ .stack_mem = bleStack,
+ .stack_size = kBleTaskSize,
+ .priority = osPriorityHigh };
+
+void rsi_ble_add_matter_service(void)
+{
+ constexpr uuid_t custom_service = { .size = RSI_BLE_MATTER_CUSTOM_SERVICE_SIZE,
+ .val = { .val16 = RSI_BLE_MATTER_CUSTOM_SERVICE_VALUE_16 } };
+ uint8_t data[RSI_BLE_MATTER_CUSTOM_SERVICE_DATA_LENGTH] = { RSI_BLE_MATTER_CUSTOM_SERVICE_DATA };
+
+ constexpr uuid_t custom_characteristic_RX = { .size = RSI_BLE_CUSTOM_CHARACTERISTIC_RX_SIZE,
+ .reserved = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_RESERVED },
+ .val = { .val128 = {
+ .data1 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_1 },
+ .data2 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_2 },
+ .data3 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_3 },
+ .data4 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_4 } } } };
+
+ rsi_ble_resp_add_serv_t new_serv_resp = { 0 };
+ rsi_ble_add_service(custom_service, &new_serv_resp);
+
+ // Adding custom characteristic declaration to the custom service
+ SilabsBleWrapper::rsi_ble_add_char_serv_att(
+ new_serv_resp.serv_handler, new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_ATTRIBUTE_HANDLE_LOCATION,
+ RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ, // Set read, write, write without response
+ new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_VALUE_HANDLE_LOCATION, custom_characteristic_RX);
+
+ // Adding characteristic value attribute to the service
+ SilabsBleWrapper::rsi_ble_add_char_val_att(
+ new_serv_resp.serv_handler, new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_VALUE_HANDLE_LOCATION,
+ custom_characteristic_RX,
+ RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ, // Set read, write, write without response
+ data, sizeof(data), ATT_REC_IN_HOST);
+
+ constexpr uuid_t custom_characteristic_TX = { .size = RSI_BLE_CUSTOM_CHARACTERISTIC_TX_SIZE,
+ .reserved = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_RESERVED },
+ .val = { .val128 = {
+ .data1 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_1 },
+ .data2 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_2 },
+ .data3 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_3 },
+ .data4 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_4 } } } };
+
+ // Adding custom characteristic declaration to the custom service
+ SilabsBleWrapper::rsi_ble_add_char_serv_att(
+ new_serv_resp.serv_handler, new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_ATTRIBUTE_HANDLE_LOCATION,
+ RSI_BLE_ATT_PROPERTY_WRITE_NO_RESPONSE | RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ |
+ RSI_BLE_ATT_PROPERTY_NOTIFY | RSI_BLE_ATT_PROPERTY_INDICATE, // Set read, write, write without response
+ new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_MEASUREMENT_HANDLE_LOCATION, custom_characteristic_TX);
+
+ // Adding characteristic value attribute to the service
+ rsi_ble_measurement_hndl = new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_MEASUREMENT_HANDLE_LOCATION;
+
+ // Adding characteristic value attribute to the service
+ rsi_ble_gatt_server_client_config_hndl =
+ new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_GATT_SERVER_CLIENT_HANDLE_LOCATION;
+
+ SilabsBleWrapper::rsi_ble_add_char_val_att(new_serv_resp.serv_handler, rsi_ble_measurement_hndl, custom_characteristic_TX,
+ RSI_BLE_ATT_PROPERTY_WRITE_NO_RESPONSE | RSI_BLE_ATT_PROPERTY_WRITE |
+ RSI_BLE_ATT_PROPERTY_READ | RSI_BLE_ATT_PROPERTY_NOTIFY |
+ RSI_BLE_ATT_PROPERTY_INDICATE, // Set read, write, write without response
+ data, sizeof(data), ATT_REC_MAINTAIN_IN_HOST);
+}
+
} // namespace
BLEManagerImpl BLEManagerImpl::sInstance;
@@ -120,15 +181,14 @@ void BLEManagerImpl::ProcessEvent(SilabsBleWrapper::BleEvent_t inEvent)
switch (inEvent.eventType)
{
case SilabsBleWrapper::BleEventType::RSI_BLE_CONN_EVENT: {
- BLEMgrImpl().HandleConnectEvent((inEvent.eventData));
+ BLEMgrImpl().HandleConnectEvent(inEvent.eventData);
// Requests the connection parameters change with the remote device
- rsi_ble_conn_params_update(inEvent.eventData->resp_enh_conn.dev_addr, BLE_MIN_CONNECTION_INTERVAL_MS,
+ rsi_ble_conn_params_update(inEvent.eventData.resp_enh_conn.dev_addr, BLE_MIN_CONNECTION_INTERVAL_MS,
BLE_MAX_CONNECTION_INTERVAL_MS, BLE_SLAVE_LATENCY_MS, BLE_TIMEOUT_MS);
- rsi_ble_set_data_len(inEvent.eventData->resp_enh_conn.dev_addr, RSI_BLE_TX_OCTETS, RSI_BLE_TX_TIME);
+ rsi_ble_set_data_len(inEvent.eventData.resp_enh_conn.dev_addr, RSI_BLE_TX_OCTETS, RSI_BLE_TX_TIME);
// Used to send the Indication confirmation
- memcpy(dev_address, inEvent.eventData->resp_enh_conn.dev_addr, RSI_DEV_ADDR_LEN);
- ble_measurement_hndl = inEvent.eventData->rsi_ble_measurement_hndl;
+ memcpy(dev_address, inEvent.eventData.resp_enh_conn.dev_addr, RSI_DEV_ADDR_LEN);
}
break;
case SilabsBleWrapper::BleEventType::RSI_BLE_DISCONN_EVENT: {
@@ -143,7 +203,7 @@ void BLEManagerImpl::ProcessEvent(SilabsBleWrapper::BleEvent_t inEvent)
break;
case SilabsBleWrapper::BleEventType::RSI_BLE_EVENT_GATT_RD: {
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
- if (inEvent.eventData->rsi_ble_read_req->type == 0)
+ if (inEvent.eventData.rsi_ble_read_req->type == 0)
{
BLEMgrImpl().HandleC3ReadRequest(inEvent.eventData);
}
@@ -220,10 +280,10 @@ void BLEManagerImpl::sl_ble_init()
SilabsBleWrapper::rsi_ble_on_event_indication_confirmation, NULL);
// Exchange of GATT info with BLE stack
- SilabsBleWrapper::rsi_ble_add_matter_service();
+ rsi_ble_add_matter_service();
rsi_ble_set_random_address_with_value(randomAddrBLE);
- sInstance.sBleEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(WfxEvent_t), NULL);
+ sInstance.sBleEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(SilabsBleWrapper::BleEvent_t), NULL);
VerifyOrDie(sInstance.sBleEventQueue != nullptr);
chip::DeviceLayer::Internal::BLEMgrImpl().HandleBootEvent();
@@ -440,7 +500,7 @@ CHIP_ERROR BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const Chi
PacketBufferHandle data)
{
int32_t status = 0;
- status = rsi_ble_indicate_value(dev_address, ble_measurement_hndl, data->DataLength(), data->Start());
+ status = rsi_ble_indicate_value(dev_address, rsi_ble_measurement_hndl, data->DataLength(), data->Start());
if (status != RSI_SUCCESS)
{
ChipLogProgress(DeviceLayer, "indication failed with error code %lx ", status);
@@ -734,9 +794,9 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
return err;
}
-void BLEManagerImpl::UpdateMtu(SilabsBleWrapper::sl_wfx_msg_t * evt)
+void BLEManagerImpl::UpdateMtu(const SilabsBleWrapper::sl_wfx_msg_t & evt)
{
- CHIPoBLEConState * bleConnState = GetConnectionState(evt->connectionHandle);
+ CHIPoBLEConState * bleConnState = GetConnectionState(evt.connectionHandle);
if (bleConnState != NULL)
{
// bleConnState->MTU is a 10-bit field inside a uint16_t. We're
@@ -748,10 +808,10 @@ void BLEManagerImpl::UpdateMtu(SilabsBleWrapper::sl_wfx_msg_t * evt)
// TODO: https://github.com/project-chip/connectedhomeip/issues/2569
// tracks making this safe with a check or explaining why no check
// is needed.
- ChipLogProgress(DeviceLayer, "DriveBLEState UpdateMtu %d", evt->rsi_ble_mtu.mtu_size);
+ ChipLogProgress(DeviceLayer, "DriveBLEState UpdateMtu %d", evt.rsi_ble_mtu.mtu_size);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
- bleConnState->mtu = evt->rsi_ble_mtu.mtu_size;
+ bleConnState->mtu = evt.rsi_ble_mtu.mtu_size;
#pragma GCC diagnostic pop
;
}
@@ -763,14 +823,13 @@ void BLEManagerImpl::HandleBootEvent(void)
PlatformMgr().ScheduleWork(DriveBLEState, 0);
}
-void BLEManagerImpl::HandleConnectEvent(SilabsBleWrapper::sl_wfx_msg_t * evt)
+void BLEManagerImpl::HandleConnectEvent(const SilabsBleWrapper::sl_wfx_msg_t & evt)
{
- AddConnection(evt->connectionHandle, evt->bondingHandle);
+ AddConnection(evt.connectionHandle, evt.bondingHandle);
PlatformMgr().ScheduleWork(DriveBLEState, 0);
}
-// TODO:: Implementation need to be done.
-void BLEManagerImpl::HandleConnectionCloseEvent(SilabsBleWrapper::sl_wfx_msg_t * evt)
+void BLEManagerImpl::HandleConnectionCloseEvent(const SilabsBleWrapper::sl_wfx_msg_t & evt)
{
uint8_t connHandle = 1;
@@ -780,7 +839,7 @@ void BLEManagerImpl::HandleConnectionCloseEvent(SilabsBleWrapper::sl_wfx_msg_t *
event.Type = DeviceEventType::kCHIPoBLEConnectionError;
event.CHIPoBLEConnectionError.ConId = connHandle;
- switch (evt->reason)
+ switch (evt.reason)
{
case RSI_BT_CTRL_REMOTE_USER_TERMINATED:
@@ -792,7 +851,7 @@ void BLEManagerImpl::HandleConnectionCloseEvent(SilabsBleWrapper::sl_wfx_msg_t *
event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
}
- ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %x)", connHandle, evt->reason);
+ ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %x)", connHandle, evt.reason);
PlatformMgr().PostEventOrDie(&event);
@@ -804,11 +863,11 @@ void BLEManagerImpl::HandleConnectionCloseEvent(SilabsBleWrapper::sl_wfx_msg_t *
}
}
-void BLEManagerImpl::HandleWriteEvent(SilabsBleWrapper::sl_wfx_msg_t * evt)
+void BLEManagerImpl::HandleWriteEvent(const SilabsBleWrapper::sl_wfx_msg_t & evt)
{
- ChipLogProgress(DeviceLayer, "Char Write Req, packet type %d", evt->rsi_ble_write.pkt_type);
+ ChipLogProgress(DeviceLayer, "Char Write Req, packet type %d", evt.rsi_ble_write.pkt_type);
- if (evt->rsi_ble_write.handle[0] == (uint8_t) evt->rsi_ble_gatt_server_client_config_hndl) // TODO:: compare the handle exactly
+ if (evt.rsi_ble_write.handle[0] == (uint8_t) rsi_ble_gatt_server_client_config_hndl) // TODO:: compare the handle exactly
{
HandleTXCharCCCDWrite(evt);
}
@@ -818,23 +877,22 @@ void BLEManagerImpl::HandleWriteEvent(SilabsBleWrapper::sl_wfx_msg_t * evt)
}
}
-// TODO:: Need to implement this
-void BLEManagerImpl::HandleTXCharCCCDWrite(SilabsBleWrapper::sl_wfx_msg_t * evt)
+void BLEManagerImpl::HandleTXCharCCCDWrite(const SilabsBleWrapper::sl_wfx_msg_t & evt)
{
CHIP_ERROR err = CHIP_NO_ERROR;
bool isIndicationEnabled = false;
ChipDeviceEvent event;
CHIPoBLEConState * bleConnState;
- bleConnState = GetConnectionState(evt->connectionHandle);
+ bleConnState = GetConnectionState(evt.connectionHandle);
VerifyOrExit(bleConnState != NULL, err = CHIP_ERROR_NO_MEMORY);
// Determine if the client is enabling or disabling notification/indication.
- if (evt->rsi_ble_write.att_value[0] != 0)
+ if (evt.rsi_ble_write.att_value[0] != 0)
{
isIndicationEnabled = true;
}
- ChipLogProgress(DeviceLayer, "HandleTXcharCCCDWrite - Config Flags value : %d", evt->rsi_ble_write.att_value[0]);
+ ChipLogProgress(DeviceLayer, "HandleTXcharCCCDWrite - Config Flags value : %d", evt.rsi_ble_write.att_value[0]);
ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", isIndicationEnabled ? "subscribe" : "unsubscribe");
if (isIndicationEnabled)
@@ -864,13 +922,13 @@ void BLEManagerImpl::HandleTXCharCCCDWrite(SilabsBleWrapper::sl_wfx_msg_t * evt)
}
}
-void BLEManagerImpl::HandleRXCharWrite(SilabsBleWrapper::sl_wfx_msg_t * evt)
+void BLEManagerImpl::HandleRXCharWrite(const SilabsBleWrapper::sl_wfx_msg_t & evt)
{
uint8_t conId = 1;
CHIP_ERROR err = CHIP_NO_ERROR;
System::PacketBufferHandle buf;
- uint16_t writeLen = evt->rsi_ble_write.length;
- uint8_t * data = (uint8_t *) evt->rsi_ble_write.att_value;
+ uint16_t writeLen = evt.rsi_ble_write.length;
+ uint8_t * data = (uint8_t *) evt.rsi_ble_write.att_value;
// Copy the data to a packet buffer.
buf = System::PacketBufferHandle::NewWithData(data, writeLen, 0, 0);
@@ -997,9 +1055,9 @@ CHIP_ERROR BLEManagerImpl::EncodeAdditionalDataTlv()
return err;
}
-void BLEManagerImpl::HandleC3ReadRequest(SilabsBleWrapper::sl_wfx_msg_t * evt)
+void BLEManagerImpl::HandleC3ReadRequest(const SilabsBleWrapper::sl_wfx_msg_t & evt)
{
- sl_status_t ret = rsi_ble_gatt_read_response(evt->rsi_ble_read_req->dev_addr, GATT_READ_RESP, evt->rsi_ble_read_req->handle,
+ sl_status_t ret = rsi_ble_gatt_read_response(evt.rsi_ble_read_req->dev_addr, GATT_READ_RESP, evt.rsi_ble_read_req->handle,
GATT_READ_ZERO_OFFSET, sInstance.c3AdditionalDataBufferHandle->DataLength(),
sInstance.c3AdditionalDataBufferHandle->Start());
if (ret != SL_STATUS_OK)
diff --git a/src/platform/silabs/rs911x/wfx_sl_ble_init.cpp b/src/platform/silabs/rs911x/wfx_sl_ble_init.cpp
index c1af13e2cd807c..971852592c3e2e 100644
--- a/src/platform/silabs/rs911x/wfx_sl_ble_init.cpp
+++ b/src/platform/silabs/rs911x/wfx_sl_ble_init.cpp
@@ -26,9 +26,6 @@
using namespace chip::DeviceLayer::Internal;
-// Global Variables
-SilabsBleWrapper::BleEvent_t bleEvent;
-
/*==============================================*/
/**
* @fn rsi_ble_on_mtu_event
@@ -40,8 +37,9 @@ SilabsBleWrapper::BleEvent_t bleEvent;
*/
void SilabsBleWrapper::rsi_ble_on_mtu_event(rsi_ble_event_mtu_t * rsi_ble_mtu)
{
- bleEvent.eventType = BleEventType::RSI_BLE_MTU_EVENT;
- memcpy(&bleEvent.eventData->rsi_ble_mtu, rsi_ble_mtu, sizeof(rsi_ble_event_mtu_t));
+ SilabsBleWrapper::BleEvent_t bleEvent = { .eventType = BleEventType::RSI_BLE_MTU_EVENT,
+ .eventData = { .connectionHandle = 1, .rsi_ble_mtu = *rsi_ble_mtu } };
+
BLEMgrImpl().BlePostEvent(&bleEvent);
}
@@ -57,9 +55,9 @@ void SilabsBleWrapper::rsi_ble_on_mtu_event(rsi_ble_event_mtu_t * rsi_ble_mtu)
*/
void SilabsBleWrapper::rsi_ble_on_gatt_write_event(uint16_t event_id, rsi_ble_event_write_t * rsi_ble_write)
{
- bleEvent.eventType = BleEventType::RSI_BLE_GATT_WRITE_EVENT;
- bleEvent.eventData->event_id = event_id;
- memcpy(&bleEvent.eventData->rsi_ble_write, rsi_ble_write, sizeof(rsi_ble_event_write_t));
+ SilabsBleWrapper::BleEvent_t bleEvent = { .eventType = BleEventType::RSI_BLE_GATT_WRITE_EVENT,
+ .eventData = {
+ .connectionHandle = 1, .event_id = event_id, .rsi_ble_write = *rsi_ble_write } };
BLEMgrImpl().BlePostEvent(&bleEvent);
}
@@ -74,10 +72,12 @@ void SilabsBleWrapper::rsi_ble_on_gatt_write_event(uint16_t event_id, rsi_ble_ev
*/
void SilabsBleWrapper::rsi_ble_on_enhance_conn_status_event(rsi_ble_event_enhance_conn_status_t * resp_enh_conn)
{
- bleEvent.eventType = BleEventType::RSI_BLE_CONN_EVENT;
- bleEvent.eventData->connectionHandle = 1;
- bleEvent.eventData->bondingHandle = 255;
- memcpy(bleEvent.eventData->resp_enh_conn.dev_addr, resp_enh_conn->dev_addr, RSI_DEV_ADDR_LEN);
+ SilabsBleWrapper::BleEvent_t bleEvent = { .eventType = BleEventType::RSI_BLE_CONN_EVENT,
+ .eventData = {
+ .connectionHandle = 1,
+ .bondingHandle = 255,
+ } };
+ memcpy(bleEvent.eventData.resp_enh_conn.dev_addr, resp_enh_conn->dev_addr, RSI_DEV_ADDR_LEN);
BLEMgrImpl().BlePostEvent(&bleEvent);
}
@@ -93,8 +93,7 @@ void SilabsBleWrapper::rsi_ble_on_enhance_conn_status_event(rsi_ble_event_enhanc
*/
void SilabsBleWrapper::rsi_ble_on_disconnect_event(rsi_ble_event_disconnect_t * resp_disconnect, uint16_t reason)
{
- bleEvent.eventType = BleEventType::RSI_BLE_DISCONN_EVENT;
- bleEvent.eventData->reason = reason;
+ SilabsBleWrapper::BleEvent_t bleEvent = { .eventType = BleEventType::RSI_BLE_DISCONN_EVENT, .eventData = { .reason = reason } };
BLEMgrImpl().BlePostEvent(&bleEvent);
}
@@ -110,9 +109,9 @@ void SilabsBleWrapper::rsi_ble_on_disconnect_event(rsi_ble_event_disconnect_t *
void SilabsBleWrapper::rsi_ble_on_event_indication_confirmation(uint16_t resp_status,
rsi_ble_set_att_resp_t * rsi_ble_event_set_att_rsp)
{
- bleEvent.eventType = BleEventType::RSI_BLE_GATT_INDICATION_CONFIRMATION;
- bleEvent.eventData->resp_status = resp_status;
- memcpy(&bleEvent.eventData->rsi_ble_event_set_att_rsp, rsi_ble_event_set_att_rsp, sizeof(rsi_ble_set_att_resp_t));
+ SilabsBleWrapper::BleEvent_t bleEvent = { .eventType = BleEventType::RSI_BLE_GATT_INDICATION_CONFIRMATION,
+ .eventData = { .resp_status = resp_status,
+ .rsi_ble_event_set_att_rsp = *rsi_ble_event_set_att_rsp } };
BLEMgrImpl().BlePostEvent(&bleEvent);
}
@@ -128,9 +127,8 @@ void SilabsBleWrapper::rsi_ble_on_event_indication_confirmation(uint16_t resp_st
*/
void SilabsBleWrapper::rsi_ble_on_read_req_event(uint16_t event_id, rsi_ble_read_req_t * rsi_ble_read_req)
{
- bleEvent.eventType = BleEventType::RSI_BLE_EVENT_GATT_RD;
- bleEvent.eventData->event_id = event_id;
- memcpy(&bleEvent.eventData->rsi_ble_read_req, rsi_ble_read_req, sizeof(rsi_ble_read_req_t));
+ SilabsBleWrapper::BleEvent_t bleEvent = { .eventType = BleEventType::RSI_BLE_EVENT_GATT_RD,
+ .eventData = { .event_id = event_id, .rsi_ble_read_req = rsi_ble_read_req } };
BLEMgrImpl().BlePostEvent(&bleEvent);
}
@@ -282,77 +280,3 @@ void SilabsBleWrapper::rsi_ble_add_char_val_att(void * serv_handler, uint16_t ha
return;
}
-
-/*==============================================*/
-/**
- * @fn rsi_ble_add_matter_service
- * @brief this function is used to add service for matter
- * @return status (uint32_t) 0 for success.
- * @section description
- * This function is used at application to create new service.
- */
-
-uint32_t SilabsBleWrapper::rsi_ble_add_matter_service(void)
-{
- uuid_t custom_service = { RSI_BLE_MATTER_CUSTOM_SERVICE_UUID };
- custom_service.size = RSI_BLE_MATTER_CUSTOM_SERVICE_SIZE;
- custom_service.val.val16 = RSI_BLE_MATTER_CUSTOM_SERVICE_VALUE_16;
- uint8_t data[RSI_BLE_MATTER_CUSTOM_SERVICE_DATA_LENGTH] = { RSI_BLE_MATTER_CUSTOM_SERVICE_DATA };
-
- static const uuid_t custom_characteristic_RX = {
- .size = RSI_BLE_CUSTOM_CHARACTERISTIC_RX_SIZE,
- .reserved = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_RESERVED },
- .val = { .val128 = { .data1 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_1 },
- .data2 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_2 },
- .data3 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_3 },
- .data4 = { RSI_BLE_CUSTOM_CHARACTERISTIC_RX_VALUE_128_DATA_4 } } }
- };
-
- rsi_ble_resp_add_serv_t new_serv_resp = { 0 };
- rsi_ble_add_service(custom_service, &new_serv_resp);
-
- // Adding custom characteristic declaration to the custom service
- rsi_ble_add_char_serv_att(
- new_serv_resp.serv_handler, new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_ATTRIBUTE_HANDLE_LOCATION,
- RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ, // Set read, write, write without response
- new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_VALUE_HANDLE_LOCATION, custom_characteristic_RX);
-
- // Adding characteristic value attribute to the service
- rsi_ble_add_char_val_att(new_serv_resp.serv_handler,
- new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_RX_VALUE_HANDLE_LOCATION, custom_characteristic_RX,
- RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ, // Set read, write, write without response
- data, sizeof(data), ATT_REC_IN_HOST);
-
- static const uuid_t custom_characteristic_TX = {
- .size = RSI_BLE_CUSTOM_CHARACTERISTIC_TX_SIZE,
- .reserved = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_RESERVED },
- .val = { .val128 = { .data1 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_1 },
- .data2 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_2 },
- .data3 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_3 },
- .data4 = { RSI_BLE_CUSTOM_CHARACTERISTIC_TX_VALUE_128_DATA_4 } } }
- };
-
- // Adding custom characteristic declaration to the custom service
- rsi_ble_add_char_serv_att(
- new_serv_resp.serv_handler, new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_ATTRIBUTE_HANDLE_LOCATION,
- RSI_BLE_ATT_PROPERTY_WRITE_NO_RESPONSE | RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ |
- RSI_BLE_ATT_PROPERTY_NOTIFY | RSI_BLE_ATT_PROPERTY_INDICATE, // Set read, write, write without response
- new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_MEASUREMENT_HANDLE_LOCATION, custom_characteristic_TX);
-
- // Adding characteristic value attribute to the service
- bleEvent.eventData->rsi_ble_measurement_hndl =
- new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_MEASUREMENT_HANDLE_LOCATION;
-
- // Adding characteristic value attribute to the service
- bleEvent.eventData->rsi_ble_gatt_server_client_config_hndl =
- new_serv_resp.start_handle + RSI_BLE_CHARACTERISTIC_TX_GATT_SERVER_CLIENT_HANDLE_LOCATION;
-
- rsi_ble_add_char_val_att(new_serv_resp.serv_handler, bleEvent.eventData->rsi_ble_measurement_hndl, custom_characteristic_TX,
- RSI_BLE_ATT_PROPERTY_WRITE_NO_RESPONSE | RSI_BLE_ATT_PROPERTY_WRITE | RSI_BLE_ATT_PROPERTY_READ |
- RSI_BLE_ATT_PROPERTY_NOTIFY |
- RSI_BLE_ATT_PROPERTY_INDICATE, // Set read, write, write without response
- data, sizeof(data), ATT_REC_MAINTAIN_IN_HOST);
-
- memset(&data, 0, sizeof(data));
- return 0;
-}
diff --git a/src/platform/silabs/rs911x/wfx_sl_ble_init.h b/src/platform/silabs/rs911x/wfx_sl_ble_init.h
index 1e770de0727100..54351674ef121e 100644
--- a/src/platform/silabs/rs911x/wfx_sl_ble_init.h
+++ b/src/platform/silabs/rs911x/wfx_sl_ble_init.h
@@ -104,15 +104,13 @@ class SilabsBleWrapper
rsi_ble_event_disconnect_t * resp_disconnect;
rsi_ble_read_req_t * rsi_ble_read_req;
rsi_ble_set_att_resp_t rsi_ble_event_set_att_rsp;
- uint16_t rsi_ble_measurement_hndl;
- uint16_t rsi_ble_gatt_server_client_config_hndl;
uint16_t subscribed;
};
struct BleEvent_t
{
BleEventType eventType;
- sl_wfx_msg_t * eventData;
+ sl_wfx_msg_t eventData;
};
// ALL Ble functions
@@ -129,7 +127,6 @@ class SilabsBleWrapper
uuid_t att_val_uuid);
static void rsi_ble_add_char_val_att(void * serv_handler, uint16_t handle, uuid_t att_type_uuid, uint8_t val_prop,
uint8_t * data, uint8_t data_len, uint8_t auth_read);
- static uint32_t rsi_ble_add_matter_service(void);
};
} // namespace Internal
diff --git a/src/python_testing/TC_DeviceBasicComposition.py b/src/python_testing/TC_DeviceBasicComposition.py
index 59182fa4e2fcb2..0f227c2c672ea4 100644
--- a/src/python_testing/TC_DeviceBasicComposition.py
+++ b/src/python_testing/TC_DeviceBasicComposition.py
@@ -108,7 +108,8 @@
from chip.clusters.ClusterObjects import ClusterAttributeDescriptor, ClusterObjectFieldDescriptor
from chip.interaction_model import InteractionModelError, Status
from chip.testing.basic_composition import BasicCompositionTests
-from chip.testing.global_attribute_ids import AttributeIdType, ClusterIdType, GlobalAttributeIds, attribute_id_type, cluster_id_type
+from chip.testing.global_attribute_ids import (AttributeIdType, ClusterIdType, CommandIdType, GlobalAttributeIds, attribute_id_type,
+ cluster_id_type, command_id_type)
from chip.testing.matter_testing import (AttributePathLocation, ClusterPathLocation, CommandPathLocation, MatterBaseTest, TestStep,
async_test_body, default_matter_test_main)
from chip.testing.taglist_and_topology_test import (create_device_type_list_for_root, create_device_type_lists,
@@ -503,7 +504,7 @@ class RequiredMandatoryAttribute:
location = CommandPathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, command_id=bad_cmd_id)
vendor_id = get_vendor_id(bad_cmd_id)
self.record_error(self.get_test_name(
- ), location=location, problem=f'Command 0x{bad_cmd_id:08x} with bad prefix 0x{vendor_id:04x} in cluster 0x{cluster_id:08x}', spec_location='Manufacturer Extensible Identifier (MEI)')
+ ), location=location, problem=f'Command 0x{bad_cmd_id:08x} with bad prefix 0x{vendor_id:04x} in cluster 0x{cluster_id:08x}' + (' (Test Vendor)' if command_id_type(bad_cmd_id) == CommandIdType.kTest else ''), spec_location='Manufacturer Extensible Identifier (MEI)')
success = False
self.print_step(7, "Validate that none of the MEI global attribute IDs contain values outside of the allowed suffix range")
diff --git a/src/python_testing/TC_TSTAT_4_2.py b/src/python_testing/TC_TSTAT_4_2.py
index 6dad144f3050c4..85ff487a9dc639 100644
--- a/src/python_testing/TC_TSTAT_4_2.py
+++ b/src/python_testing/TC_TSTAT_4_2.py
@@ -37,6 +37,7 @@
import copy
import logging
import random
+from collections import namedtuple
import chip.clusters as Clusters
from chip import ChipDeviceCtrl # Needed before chip.FabricAdmin
@@ -418,11 +419,6 @@ async def test_TC_TSTAT_4_2(self):
logger.info(
"Couldn't run test step 4 since there were no built-in presets")
- # Send the SetActivePresetRequest command
- await self.send_set_active_preset_handle_request_command(value=b'\x03')
-
- activePresetHandle = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.ActivePresetHandle)
-
self.step("5")
if self.pics_guard(self.check_pics("TSTAT.S.F08") and self.check_pics("TSTAT.S.A0050") and self.check_pics("TSTAT.S.Cfe.Rsp")):
@@ -714,6 +710,28 @@ async def test_TC_TSTAT_4_2(self):
self.step("18")
if self.pics_guard(self.check_pics("TSTAT.S.F08") and self.check_pics("TSTAT.S.A0050") and self.check_pics("TSTAT.S.Cfe.Rsp")):
+ ScenarioHeadroom = namedtuple("ScenarioHeadroom", "presetScenario remaining")
+ # Generate list of tuples of scenarios and number of remaining presets per scenario allowed
+ presetScenarioHeadrooms = list(ScenarioHeadroom(presetType.presetScenario,
+ presetType.numberOfPresets - presetScenarioCounts.get(presetType.presetScenario, 0)) for presetType in presetTypes)
+
+ if presetScenarioHeadrooms:
+ # Find the preset scenario with the smallest number of remaining allowed presets
+ presetScenarioHeadrooms = sorted(presetScenarioHeadrooms, key=lambda psh: psh.remaining)
+ presetScenarioHeadroom = presetScenarioHeadrooms[0]
+
+ # Add one more preset than is allowed by the preset type
+ test_presets = copy.deepcopy(current_presets)
+ test_presets.extend([cluster.Structs.PresetStruct(presetHandle=NullValue, presetScenario=presetScenarioHeadroom.presetScenario,
+ coolingSetpoint=coolSetpoint, heatingSetpoint=heatSetpoint, builtIn=False)] * (presetScenarioHeadroom.remaining + 1))
+
+ await self.send_atomic_request_begin_command()
+
+ await self.write_presets(endpoint=endpoint, presets=test_presets, expected_status=Status.ResourceExhausted)
+
+ # Clear state for next test.
+ await self.send_atomic_request_rollback_command()
+
# Calculate the length of the Presets list that could be created using the preset scenarios in PresetTypes and numberOfPresets supported for each scenario.
totalExpectedPresetsLength = sum(presetType.numberOfPresets for presetType in presetTypes)
diff --git a/src/python_testing/TestIdChecks.py b/src/python_testing/TestIdChecks.py
index eda01ef9556493..c86d4bfe6d0d0b 100644
--- a/src/python_testing/TestIdChecks.py
+++ b/src/python_testing/TestIdChecks.py
@@ -15,9 +15,9 @@
# limitations under the License.
#
-from chip.testing.global_attribute_ids import (AttributeIdType, ClusterIdType, DeviceTypeIdType, attribute_id_type, cluster_id_type,
- device_type_id_type, is_valid_attribute_id, is_valid_cluster_id,
- is_valid_device_type_id)
+from chip.testing.global_attribute_ids import (AttributeIdType, ClusterIdType, CommandIdType, DeviceTypeIdType, attribute_id_type,
+ cluster_id_type, command_id_type, device_type_id_type, is_valid_attribute_id,
+ is_valid_cluster_id, is_valid_command_id, is_valid_device_type_id)
from chip.testing.matter_testing import MatterBaseTest, default_matter_test_main
from mobly import asserts
@@ -210,6 +210,71 @@ def check_all_bad(id):
for id in prefix_bad:
check_all_bad(id)
+ def test_command_ids(self):
+ standard_global_good = [0x0000_00E0, 0x0000_00FF, 0x0000_00E1, 0x0000_00FE]
+ standard_global_bad = [0x0000_01E0, 0x0000_0FFF, 0x0000_AAE1, 0x0000_BBFE, 0x0000_FFFF]
+ scoped_non_global_good = [0x0000_0000, 0x0000_00DF, 0x0000_0001]
+ scoped_non_global_bad = [0x0000_0F00, 0x0000_01DF, 0x0000_0F01]
+ manufacturer_good = [0x0001_0000, 0x0001_00FF, 0xFFF0_0000, 0xFFF0_00FF, 0x0001_00FE]
+ manufacturer_bad = [0x0001_0A00, 0x0001_0BFF, 0x0001_FFFF, 0xFFF0_0C00, 0xFFF0_D0FF, 0x0001_F0FE]
+ test_good = [0xFFF1_0000, 0xFFF1_00E0, 0xFFF1_00FF, 0xFFF4_0000, 0xFFF4_00E0, 0xFFF4_00FF]
+ test_bad = [0xFFF1_5000, 0xFFF1_F000, 0xFFF1_FFFF, 0xFFF4_5000, 0xFFF4_F000, 0xFFF4_FFFF]
+ prefix_bad = [0xFFF5_0000, 0xFFF5_4FFF, 0xFFF5_5000, 0xFFF5_F000, 0xFFF5_FFFF]
+
+ def check_standard_global(id):
+ id_type = command_id_type(id)
+ msg = f"Incorrect command range assessment, expecting standard global {id:08x}, type = {id_type}"
+ asserts.assert_equal(id_type, CommandIdType.kStandardGlobal, msg)
+ asserts.assert_true(is_valid_command_id(id_type, allow_test=True), msg)
+ asserts.assert_true(is_valid_command_id(id_type, allow_test=False), msg)
+
+ def check_scoped_non_global(id):
+ id_type = command_id_type(id)
+ msg = f"Incorrect command range assessment, expecting scoped non-global {id:08x}, type = {id_type}"
+ asserts.assert_equal(id_type, CommandIdType.kScopedNonGlobal, msg)
+ asserts.assert_true(is_valid_command_id(id_type, allow_test=True), msg)
+ asserts.assert_true(is_valid_command_id(id_type, allow_test=False), msg)
+
+ def check_manufacturer(id):
+ id_type = command_id_type(id)
+ msg = f"Incorrect command range assessment, expecting manufacturer {id:08x}, type = {id_type}"
+ asserts.assert_equal(id_type, CommandIdType.kManufacturer, msg)
+ asserts.assert_true(is_valid_command_id(id_type, allow_test=True), msg)
+ asserts.assert_true(is_valid_command_id(id_type, allow_test=False), msg)
+
+ def check_test(id):
+ id_type = command_id_type(id)
+ msg = f"Incorrect command range assessment, expecting test {id:08x}, type = {id_type}"
+ asserts.assert_equal(id_type, CommandIdType.kTest, msg)
+ asserts.assert_true(is_valid_command_id(id_type, allow_test=True), msg)
+ asserts.assert_false(is_valid_command_id(id_type, allow_test=False), msg)
+
+ def check_all_bad(id):
+ id_type = command_id_type(id)
+ msg = f"Incorrect command range assessment, expecting invalid {id:08x}, type = {id_type}"
+ asserts.assert_equal(id_type, CommandIdType.kInvalid, msg)
+ asserts.assert_false(is_valid_command_id(id_type, allow_test=True), msg)
+ asserts.assert_false(is_valid_command_id(id_type, allow_test=False), msg)
+
+ for id in standard_global_good:
+ check_standard_global(id)
+ for id in standard_global_bad:
+ check_all_bad(id)
+ for id in scoped_non_global_good:
+ check_scoped_non_global(id)
+ for id in scoped_non_global_bad:
+ check_all_bad(id)
+ for id in manufacturer_good:
+ check_manufacturer(id)
+ for id in manufacturer_bad:
+ check_all_bad(id)
+ for id in test_good:
+ check_test(id)
+ for id in test_bad:
+ check_all_bad(id)
+ for id in prefix_bad:
+ check_all_bad(id)
+
if __name__ == "__main__":
default_matter_test_main()
diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/global_attribute_ids.py b/src/python_testing/matter_testing_infrastructure/chip/testing/global_attribute_ids.py
index e692adfdfb5a10..f9fbd2e2ade835 100644
--- a/src/python_testing/matter_testing_infrastructure/chip/testing/global_attribute_ids.py
+++ b/src/python_testing/matter_testing_infrastructure/chip/testing/global_attribute_ids.py
@@ -61,6 +61,15 @@ class AttributeIdType(Enum):
kManufacturer = auto(),
kTest = auto(),
+
+class CommandIdType(Enum):
+ kInvalid = auto()
+ kStandardGlobal = auto(),
+ kScopedNonGlobal = auto(),
+ kManufacturer = auto(),
+ kTest = auto(),
+
+
# ID helper classes - this allows us to use the values from the prefix and suffix table directly
# because the class handles the non-inclusive range.
@@ -92,6 +101,9 @@ def __contains__(self, id: int):
CLUSTER_ID_MANUFACTURER_RANGE_SUFFIX = SuffixIdRange(0xFC00, 0xFFFE)
ATTRIBUTE_ID_GLOBAL_RANGE_SUFFIX = SuffixIdRange(0xF000, 0xFFFE)
ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX = SuffixIdRange(0x0000, 0x4FFF)
+COMMAND_ID_GLOBAL_STANDARD_SUFFIX = SuffixIdRange(0x00E0, 0x00FF)
+COMMAND_ID_NON_GLOBAL_SCOPED_SUFFIX = SuffixIdRange(0x0000, 0x00DF)
+COMMAND_ID_SUFFIX = SuffixIdRange(0x0000, 0x00FF)
def device_type_id_type(id: int) -> DeviceTypeIdType:
@@ -145,3 +157,22 @@ def is_valid_attribute_id(id_type: AttributeIdType, allow_test: bool = False):
if allow_test:
valid.append(AttributeIdType.kTest)
return id_type in valid
+
+
+def command_id_type(id: int) -> CommandIdType:
+ if id in STANDARD_PREFIX and id in COMMAND_ID_GLOBAL_STANDARD_SUFFIX:
+ return CommandIdType.kStandardGlobal
+ if id in STANDARD_PREFIX and id in COMMAND_ID_NON_GLOBAL_SCOPED_SUFFIX:
+ return CommandIdType.kScopedNonGlobal
+ if id in MANUFACTURER_PREFIX and id in COMMAND_ID_SUFFIX:
+ return CommandIdType.kManufacturer
+ if id in TEST_PREFIX and id in COMMAND_ID_SUFFIX:
+ return CommandIdType.kTest
+ return CommandIdType.kInvalid
+
+
+def is_valid_command_id(id_type: CommandIdType, allow_test: bool = False):
+ valid = [CommandIdType.kStandardGlobal, CommandIdType.kScopedNonGlobal, CommandIdType.kManufacturer]
+ if allow_test:
+ valid.append(CommandIdType.kTest)
+ return id_type in valid
diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py
index 0a40b1688d74cf..053fa575c6452d 100644
--- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py
+++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py
@@ -919,6 +919,9 @@ class TestStep:
expectation: str = ""
is_commissioning: bool = False
+ def __str__(self):
+ return f'{self.test_plan_number}: {self.description}\tExpected outcome: {self.expectation}'
+
@dataclass
class TestInfo:
@@ -1325,7 +1328,7 @@ def extract_error_text() -> tuple[str, str]:
if not trace:
return no_stack_trace
- if isinstance(exception, signals.TestError):
+ if isinstance(exception, signals.TestError) or isinstance(exception, signals.TestFailure):
# Exception gets raised by the mobly framework, so the proximal error is one line back in the stack trace
assert_candidates = [idx for idx, line in enumerate(trace) if "asserts" in line and "asserts.py" not in line]
if not assert_candidates:
@@ -1343,6 +1346,9 @@ def extract_error_text() -> tuple[str, str]:
return probable_error.strip(), trace[file_candidates[-1]].strip()
probable_error, probable_file = extract_error_text()
+ test_steps = self.get_defined_test_steps(self.current_test_info.name)
+ test_step = str(test_steps[self.current_step_index-1]
+ ) if test_steps is not None else 'UNKNOWN - no test steps provided in test script'
logging.error(textwrap.dedent(f"""
******************************************************************
@@ -1353,8 +1359,12 @@ def extract_error_text() -> tuple[str, str]:
* {probable_file}
* {probable_error}
*
+ * Test step:
+ * {test_step}
+ *
+ * Endpoint: {self.matter_test_config.endpoint}
+ *
*******************************************************************
-
"""))
def on_pass(self, record):
diff --git a/third_party/openthread/platforms/efr32/BUILD.gn b/third_party/openthread/platforms/efr32/BUILD.gn
index 69e55a5d76151d..e270db2ae8757f 100644
--- a/third_party/openthread/platforms/efr32/BUILD.gn
+++ b/third_party/openthread/platforms/efr32/BUILD.gn
@@ -65,7 +65,6 @@ source_set("libopenthread-efr32") {
"${sl_ot_efr32_root}/flash.c",
"${sl_ot_efr32_root}/ieee802154-packet-utils.cpp",
"${sl_ot_efr32_root}/misc.c",
- "${sl_ot_efr32_root}/radio.c",
"${sl_ot_efr32_root}/radio_coex.c",
"${sl_ot_efr32_root}/radio_extension.c",
"${sl_ot_efr32_root}/radio_power_manager.c",
@@ -73,6 +72,9 @@ source_set("libopenthread-efr32") {
"${sl_ot_efr32_root}/sleep.c",
"${sl_ot_efr32_root}/soft_source_match_table.c",
"${sl_ot_efr32_root}/system.c",
+
+ # Temporary file until the files in the SI SDK is fixed
+ "${sdk_support_root}/protocol/openthread/platform-abstraction/efr32/radio.c",
]
include_dirs = [ "${openthread_root}/examples/platforms/utils" ]
diff --git a/third_party/openthread/repo b/third_party/openthread/repo
index 2aeb8b833ba760..287dbfa25130ea 160000
--- a/third_party/openthread/repo
+++ b/third_party/openthread/repo
@@ -1 +1 @@
-Subproject commit 2aeb8b833ba760ec29d5f340dd1ce7bcb61c5d56
+Subproject commit 287dbfa25130ead5010877e934effbb0a2534265
diff --git a/third_party/silabs/BUILD.gn b/third_party/silabs/BUILD.gn
index e08c7cd0bd11bd..16e0ba68c4607a 100644
--- a/third_party/silabs/BUILD.gn
+++ b/third_party/silabs/BUILD.gn
@@ -206,7 +206,9 @@ if (wifi_soc != true) { # CCP board
"${openthread_root}/src/core/mac/mac_frame.cpp",
"${openthread_root}/src/core/mac/sub_mac.cpp",
"${openthread_root}/src/core/thread/mle.cpp",
- "${sl_ot_platform_abstraction}/efr32/radio.c",
+
+ # Temporary file until the files in the SI SDK is fixed
+ "${sdk_support_root}/protocol/openthread/platform-abstraction/efr32/radio.c",
]
include_dirs = [ "${sl_ot_platform_abstraction}/include" ]
diff --git a/third_party/silabs/lwip.gni b/third_party/silabs/lwip.gni
index b0b6a0db0d2c9f..9a35e7c45f7a61 100644
--- a/third_party/silabs/lwip.gni
+++ b/third_party/silabs/lwip.gni
@@ -169,10 +169,8 @@ template("lwip_target") {
"${_lwip_root}/src/core/ipv6/ip6.c",
"${_lwip_root}/src/core/ipv6/ip6_addr.c",
"${_lwip_root}/src/core/ipv6/ip6_frag.c",
+ "${_lwip_root}/src/core/ipv6/mld6.c",
"${_lwip_root}/src/core/ipv6/nd6.c",
-
- # TODO: When updating to next Si SDK version, revert change.
- "${sdk_support_root}/src/core/ipv6/mld6.c",
]
}
diff --git a/third_party/silabs/matter_support b/third_party/silabs/matter_support
index 8dd7b9bb5f8577..bf647de36d841e 160000
--- a/third_party/silabs/matter_support
+++ b/third_party/silabs/matter_support
@@ -1 +1 @@
-Subproject commit 8dd7b9bb5f8577834140bcc54f7497ae3f4b9bd0
+Subproject commit bf647de36d841e62fdac5d37c0cdfc5ebf9200bc
diff --git a/third_party/silabs/simplicity_sdk b/third_party/silabs/simplicity_sdk
index aa5ce2e835dfdc..36e12f01947c2b 160000
--- a/third_party/silabs/simplicity_sdk
+++ b/third_party/silabs/simplicity_sdk
@@ -1 +1 @@
-Subproject commit aa5ce2e835dfdce8c20fb828f27d3a261946f946
+Subproject commit 36e12f01947c2bed82922015e87b926df0745bc2
diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp
index 0b5178d3bcb208..7c4c38ae6cec3f 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp
+++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp
@@ -6495,6 +6495,8 @@ char const * DeviceTypeIdToText(chip::DeviceTypeId id)
return "EVSE";
case 0x0000050D:
return "Device Energy Management";
+ case 0x0000050F:
+ return "Water Heater";
case 0x00000510:
return "Electrical Sensor";
case 0x00000840: