[Silabs] SiWx917 folder structure skeleton in silabs folder (#23750)
* Copy of EFR32 in SiWx917 folder as the skeleton for platform changes
* restyling the PR
* Spelling corrections in the PR
* Spelling check recorrected
diff --git a/examples/lighting-app/silabs/SiWx917/.gn b/examples/lighting-app/silabs/SiWx917/.gn
new file mode 100644
index 0000000..4c078f6
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_openthread_ftd = true
+
+ import("//args.gni")
+}
diff --git a/examples/lighting-app/silabs/SiWx917/BUILD.gn b/examples/lighting-app/silabs/SiWx917/BUILD.gn
new file mode 100644
index 0000000..3a812b9
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,385 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${efr32_sdk_build_root}/efr32_executable.gni")
+import("${efr32_sdk_build_root}/efr32_sdk.gni")
+
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+import("${chip_root}/src/platform/device.gni")
+
+if (chip_enable_pw_rpc) {
+ import("//build_overrides/pigweed.gni")
+ import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+efr32_project_dir = "${chip_root}/examples/lighting-app/silabs/efr32"
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+declare_args() {
+ # Dump memory usage at link time.
+ chip_print_memory_usage = false
+
+ # Monitor & log memory usage at runtime.
+ enable_heap_monitoring = false
+
+ # Enable Sleepy end device
+ enable_sleepy_device = false
+
+ # OTA timeout in seconds
+ OTA_periodic_query_timeout = 86400
+
+ # Wifi related stuff - they are overridden by gn -args="use_wf200=true"
+ use_wf200 = false
+ use_rs911x = false
+ use_rs911x_sockets = false
+ sl_wfx_config_softap = false
+ sl_wfx_config_scan = true
+
+ # Disable LCD on supported devices
+ disable_lcd = false
+
+ # Argument to Disable IPv4 for wifi(rs911)
+ chip_enable_wifi_ipv4 = false
+
+ # Argument to force enable WPA3 security on rs91x
+ rs91x_wpa3_only = false
+}
+
+declare_args() {
+ # Enables LCD Qr Code on supported devices
+ show_qr_code = !disable_lcd
+}
+
+# qr code cannot be true if lcd is disabled
+assert(!(disable_lcd && show_qr_code))
+
+# Sanity check
+assert(!(chip_enable_wifi && chip_enable_openthread))
+assert(!(use_rs911x && chip_enable_openthread))
+assert(!(use_wf200 && chip_enable_openthread))
+if (chip_enable_wifi) {
+ assert(use_rs911x || use_wf200)
+ enable_openthread_cli = false
+ import("${chip_root}/src/platform/silabs/EFR32/wifi_args.gni")
+}
+
+# ThunderBoards, Explorer Kit and MGM240L do not support LCD (No LCD)
+if (silabs_board == "BRD4166A" || silabs_board == "BRD2601B" ||
+ silabs_board == "BRD2703A" || silabs_board == "BRD4319A") {
+ show_qr_code = false
+ disable_lcd = true
+}
+
+# WiFi settings
+if (chip_enable_wifi) {
+ # disabling LCD for MG24 for wifi
+ if (silabs_board == "BRD4186A" || silabs_board == "BRD4187A") {
+ show_qr_code = false
+ disable_lcd = true
+ }
+ wifi_sdk_dir = "${chip_root}/src/platform/silabs/EFR32/wifi"
+ efr32_lwip_defs = [ "LWIP_NETIF_API=1" ]
+ if (lwip_ipv4) {
+ efr32_lwip_defs += [
+ "LWIP_IPV4=1",
+
+ # adds following options to provide
+ # them to .cpp source files
+ # flags ported from lwipopts file
+ # TODO: move lwipopts to one location
+ "LWIP_ARP=1",
+ "LWIP_ICMP=1",
+ "LWIP_IGMP=1",
+ "LWIP_DHCP=1",
+ "LWIP_DNS=0",
+ ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV4=0" ]
+ }
+ if (lwip_ipv6) {
+ efr32_lwip_defs += [ "LWIP_IPV6=1" ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV6=0" ]
+ }
+
+ if (use_rs911x) {
+ wiseconnect_sdk_root =
+ "${chip_root}/third_party/silabs/wiseconnect-wifi-bt-sdk"
+ import("${examples_plat_dir}/rs911x/rs911x.gni")
+ } else {
+ import("${examples_plat_dir}/wf200/wf200.gni")
+ }
+}
+
+efr32_sdk("sdk") {
+ sources = [
+ "${efr32_project_dir}/include/CHIPProjectConfig.h",
+ "${examples_plat_dir}/FreeRTOSConfig.h",
+ ]
+
+ include_dirs = [
+ "${chip_root}/src/platform/silabs/EFR32",
+ "${efr32_project_dir}/include",
+ "${examples_plat_dir}",
+ "${chip_root}/src/lib",
+ "${examples_common_plat_dir}",
+ ]
+
+ defines = [
+ "BOARD_ID=${silabs_board}",
+ "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}",
+ ]
+
+ if (enable_heap_monitoring) {
+ defines += [ "HEAP_MONITORING" ]
+ }
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "HAL_VCOM_ENABLE=1",
+ "PW_RPC_ENABLED",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ defines += rs911x_defs
+ include_dirs += rs911x_plat_incs
+ } else if (use_wf200) {
+ defines += wf200_defs
+ include_dirs += wf200_plat_incs
+ }
+
+ if (use_rs911x_sockets) {
+ include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ]
+ defines += rs911x_sock_defs
+ } else {
+ # Using LWIP instead of the native TCP/IP stack
+ defines += efr32_lwip_defs
+ }
+
+ if (sl_wfx_config_softap) {
+ defines += [ "SL_WFX_CONFIG_SOFTAP" ]
+ }
+ if (sl_wfx_config_scan) {
+ defines += [ "SL_WFX_CONFIG_SCAN" ]
+ }
+ }
+}
+
+efr32_executable("lighting_app") {
+ output_name = "chip-efr32-lighting-example.out"
+ include_dirs = [ "include" ]
+ defines = []
+
+ sources = [
+ "${examples_common_plat_dir}/heap_4_silabs.c",
+ "${examples_plat_dir}/BaseApplication.cpp",
+ "${examples_plat_dir}/efr32_utils.cpp",
+ "${examples_plat_dir}/init_efrPlatform.cpp",
+ "${examples_plat_dir}/matter_config.cpp",
+ "src/AppTask.cpp",
+ "src/LightingManager.cpp",
+ "src/ZclCallbacks.cpp",
+ "src/main.cpp",
+ ]
+
+ if (use_wstk_leds) {
+ sources += [ "${examples_plat_dir}/LEDWidget.cpp" ]
+ }
+
+ if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli ||
+ use_wf200 || use_rs911x) {
+ sources += [ "${examples_plat_dir}/uart.cpp" ]
+ }
+
+ deps = [
+ ":sdk",
+ "${chip_root}/examples/lighting-app/lighting-common",
+ "${chip_root}/examples/providers:device_info_provider",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/setup_payload",
+ ]
+
+ # OpenThread Settings
+ if (chip_enable_openthread) {
+ deps += [
+ "${chip_root}/third_party/openthread:openthread",
+ "${chip_root}/third_party/openthread:openthread-platform",
+ "${examples_plat_dir}:efr-matter-shell",
+ ]
+ }
+
+ if (chip_enable_ota_requestor) {
+ defines += [ "EFR32_OTA_ENABLED" ]
+ sources += [ "${examples_plat_dir}/OTAConfig.cpp" ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ sources += rs911x_src_plat
+
+ # All the stuff from wiseconnect
+ sources += rs911x_src_sapi
+
+ # Apparently - the rsi library needs this (though we may not use use it)
+ sources += rs911x_src_sock
+ include_dirs += rs911x_inc_plat
+
+ if (use_rs911x_sockets) {
+ #
+ # Using native sockets inside RS911x
+ #
+ include_dirs += rs911x_sock_inc
+ } else {
+ #
+ # We use LWIP - not built-in sockets
+ #
+ sources += rs911x_src_lwip
+ }
+ } else if (use_wf200) {
+ sources += wf200_plat_src
+ include_dirs += wf200_plat_incs
+ }
+
+ if (chip_enable_wifi_ipv4) {
+ defines += [ "CHIP_DEVICE_CONFIG_ENABLE_IPV4" ]
+ }
+
+ if (rs91x_wpa3_only) {
+ # TODO: Change this macro once WF200 support is provided
+ defines += [ "WIFI_ENABLE_SECURITY_WPA3=1" ]
+ }
+ }
+
+ if (!disable_lcd) {
+ sources += [
+ "${examples_plat_dir}/display/demo-ui.c",
+ "${examples_plat_dir}/display/lcd.cpp",
+ ]
+
+ include_dirs += [ "${examples_plat_dir}/display" ]
+ defines += [
+ "DISPLAY_ENABLED",
+ "IS_DEMO_LIGHT=1",
+ ]
+ if (show_qr_code) {
+ defines += [ "QR_CODE_ENABLED" ]
+
+ deps += [ "${chip_root}/examples/common/QRCode" ]
+ }
+ }
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "PW_RPC_ENABLED",
+ "PW_RPC_ATTRIBUTE_SERVICE=1",
+ "PW_RPC_BUTTON_SERVICE=1",
+ "PW_RPC_DESCRIPTOR_SERVICE=1",
+ "PW_RPC_DEVICE_SERVICE=1",
+ "PW_RPC_LIGHTING_SERVICE=1",
+ "PW_RPC_OTCLI_SERVICE=1",
+ "PW_RPC_THREAD_SERVICE=1",
+ "PW_RPC_TRACING_SERVICE=1",
+ ]
+
+ sources += [
+ "${chip_root}/examples/common/pigweed/RpcService.cpp",
+ "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp",
+ "${examples_common_plat_dir}/PigweedLogger.cpp",
+ "${examples_common_plat_dir}/Rpc.cpp",
+ ]
+
+ deps += [
+ "$dir_pw_hdlc:rpc_channel_output",
+ "$dir_pw_stream:sys_io_stream",
+ "$dir_pw_trace",
+ "$dir_pw_trace_tokenized",
+ "$dir_pw_trace_tokenized:trace_rpc_service",
+ "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc",
+ "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:ot_cli_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:thread_service.nanopb_rpc",
+ "${examples_plat_dir}/pw_sys_io:pw_sys_io_efr32",
+ ]
+
+ deps += pw_build_LINK_DEPS
+
+ include_dirs += [
+ "${chip_root}/examples/common",
+ "${chip_root}/examples/common/pigweed/efr32",
+ ]
+ }
+
+ if (enable_heap_monitoring) {
+ sources += [ "${examples_common_plat_dir}/MemMonitoring.cpp" ]
+ defines += [ "HEAP_MONITORING" ]
+ }
+
+ ldscript = "${examples_plat_dir}/ldscripts/${silabs_family}.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+ if (chip_print_memory_usage) {
+ ldflags += [
+ "-Wl,--print-memory-usage",
+ "-fstack-usage",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ ldflags += [
+ "-Wl,--defsym",
+ "-Wl,SILABS_WIFI=1",
+ ]
+ }
+
+ # Attestation Credentials
+ if (chip_build_platform_attestation_credentials_provider) {
+ deps += [ "${examples_plat_dir}:efr32-attestation-credentials" ]
+ }
+
+ # Factory Data Provider
+ if (use_efr32_factory_data_provider) {
+ deps += [ "${examples_plat_dir}:efr32-factory-data-provider" ]
+ }
+
+ output_dir = root_out_dir
+}
+
+group("efr32") {
+ deps = [ ":lighting_app" ]
+}
+
+group("default") {
+ deps = [ ":efr32" ]
+}
diff --git a/examples/lighting-app/silabs/SiWx917/README.md b/examples/lighting-app/silabs/SiWx917/README.md
new file mode 100644
index 0000000..ae7565f
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/README.md
@@ -0,0 +1,424 @@
+# Matter EFR32 Lighting Example
+
+An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24.
+
+<hr>
+
+- [Matter EFR32 Lighting Example](#matter-efr32-lighting-example)
+ - [Introduction](#introduction)
+ - [Building](#building)
+ - [Flashing the Application](#flashing-the-application)
+ - [Viewing Logging Output](#viewing-logging-output)
+ - [Running the Complete Example](#running-the-complete-example)
+ - [Notes](#notes)
+ - [Running RPC console](#running-rpc-console)
+ - [Device Tracing](#device-tracing)
+ - [Memory settings](#memory-settings)
+ - [OTA Software Update](#ota-software-update)
+ - [Group Communication (Multicast)](#group-communication-multicast)
+ - [Building options](#building-options)
+ - [Disabling logging](#disabling-logging)
+ - [Debug build / release build](#debug-build--release-build)
+ - [Disabling LCD](#disabling-lcd)
+ - [KVS maximum entry count](#kvs-maximum-entry-count)
+
+<hr>
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+<a name="intro"></a>
+
+## Introduction
+
+The EFR32 lighting example provides a baseline demonstration of a Light control
+device, built using Matter and the Silicon Labs gecko SDK. It can be controlled
+by a Chip controller over an Openthread or Wifi network..
+
+The EFR32 device can be commissioned over Bluetooth Low Energy where the device
+and the Chip controller will exchange security information with the Rendez-vous
+procedure. If using Thread, Thread Network credentials are then provided to the
+EFR32 device which will then join the Thread network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+Rendez-vous procedure.
+
+The lighting example is intended to serve both as a means to explore the
+workings of Matter as well as a template for creating real products based on the
+Silicon Labs platform.
+
+<a name="building"></a>
+
+## Building
+
+- Download the
+ [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+ command line tool, and ensure that `commander` is your shell search path.
+ (For Mac OS X, `commander` is located inside
+ `Commander.app/Contents/MacOS/`.)
+
+- Download and install a suitable ARM gcc tool chain:
+ [GNU Arm Embedded Toolchain 9-2019-q4-major](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
+
+- Install some additional tools (likely already present for CHIP developers):
+
+ - Linux: `sudo apt-get install git ninja-build`
+
+ - Mac OS X: `brew install ninja`
+
+- Supported hardware:
+
+ - > For the latest supported hardware please refer to the
+ > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+ > in the Silicon Labs Matter Github Repo
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+* Build the example application:
+
+ cd ~/connectedhomeip
+ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app BRD4161A
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip
+ $ rm -rf ./out/
+
+ OR use GN/Ninja directly
+
+ $ cd ~/connectedhomeip/examples/lighting-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug
+ $ ninja -C out/debug
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip/examples/lighting-app/efr32
+ $ rm -rf out/
+
+* Build the example as Sleepy End Device (SED)
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app_SED BRD4161A --sed
+
+ or use gn as previously mentioned but adding the following arguments:
+
+ $ gn gen out/debug '--args=silabs_board="BRD4161A" enable_sleepy_device=true chip_openthread_ftd=false'
+
+* Build the example with pigweed RPC
+
+ $ ./scripts/examples/gn_efr32_example.sh examples/lighting-app/efr32/ out/lighting_app_rpc BRD4161A 'import("//with_pw_rpc.gni")'
+
+ or use GN/Ninja Directly
+
+ $ cd ~/connectedhomeip/examples/lighting-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+ $ ninja -C out/debug
+
+ [Running Pigweed RPC console](#running-pigweed-rpc-console)
+
+For more build options, help is provided when running the build script without
+arguments
+
+ ./scripts/examples/gn_efr32_example.sh
+
+<a name="flashing"></a>
+
+## Flashing the Application
+
+- On the command line:
+
+ $ cd ~/connectedhomeip/examples/lighting-app/efr32
+ $ python3 out/debug/chip-efr32-lighting-example.flash.py
+
+- Or with the Ozone debugger, just load the .out file.
+
+<a name="view-logging"></a>
+
+## Viewing Logging Output
+
+The example application is built to use the SEGGER Real Time Transfer (RTT)
+facility for log output. RTT is a feature built-in to the J-Link Interface MCU
+on the WSTK development board. It allows bi-directional communication with an
+embedded application without the need for a dedicated UART.
+
+Using the RTT facility requires downloading and installing the _SEGGER J-Link
+Software and Documentation Pack_
+([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)).
+
+Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too
+after flashing the .out file.
+
+- Download the J-Link installer by navigating to the appropriate URL and
+ agreeing to the license agreement.
+
+- [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb)
+- [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg)
+
+* Install the J-Link software
+
+ $ cd ~/Downloads
+ $ sudo dpkg -i JLink_Linux_V*_x86_64.deb
+
+* In Linux, grant the logged in user the ability to talk to the development
+ hardware via the linux tty device (/dev/ttyACMx) by adding them to the
+ dialout group.
+
+ $ sudo usermod -a -G dialout ${USER}
+
+Once the above is complete, log output can be viewed using the JLinkExe tool in
+combination with JLinkRTTClient as follows:
+
+- Run the JLinkExe tool with arguments to autoconnect to the WSTK board:
+
+ For MG12 use:
+
+ $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1
+
+ For MG21 use:
+
+ $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1
+
+- In a second terminal, run the JLinkRTTClient to view logs:
+
+ $ JLinkRTTClient
+
+<a name="running-complete-example"></a>
+
+## Running the Complete Example
+
+- It is assumed here that you already have an OpenThread border router
+ configured and running. If not see the following guide
+ [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md)
+ for more information on how to setup a border router on a raspberryPi.
+
+ Take note that the RCP code is available directly through
+ [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5)
+ under File->New->Project Wizard->Examples->Thread : ot-rcp
+
+- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR
+ Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over
+ BLE
+
+ * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2,
+ a URL can be found in the RTT logs.
+
+ <info > [SVR] Copy/paste the below URL in a browser to see the QR Code:
+ <info > [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0
+
+ **LED 0** shows the overall state of the device and its connectivity. The
+ following states are possible:
+
+ - _Short Flash On (50 ms on/950 ms off)_ ; The device is in the
+ unprovisioned (unpaired) state and is waiting for a commissioning
+ application to connect.
+
+ - _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ — The device is in the
+ unprovisioned state and a commissioning application is connected through
+ Bluetooth LE.
+
+ - _Short Flash Off_ ; (950ms on/50ms off)_ — The device is fully
+ provisioned, but does not yet have full Thread network or service
+ connectivity.
+
+ - _Solid On_ ; The device is fully provisioned and has full Thread
+ network and service connectivity.
+
+ **LED 1** Simulates the Light The following states are possible:
+
+ - _Solid On_ ; Light is on
+ - _Off_ ; Light is off
+
+ **Push Button 0**
+
+ - _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode
+ for 30 seconds. The device will then switch to a slower interval advertisement.
+ After 15 minutes, the advertisement stops.
+
+ - _Pressed and hold for 6 s_ : Initiates the factory reset of the device.
+ Releasing the button within the 6-second window cancels the factory reset
+ procedure. **LEDs** blink in unison when the factory reset procedure is
+ initiated.
+
+ **Push Button 1** Toggles the light state On/Off
+
+* You can provision and control the Chip device using the python controller,
+ Chip tool standalone, Android or iOS app
+
+* You can provision and control the Chip device using the python controller,
+ Chip tool standalone, Android or iOS app
+
+ [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+
+ Here is an example with the CHIPTool:
+
+ chip-tool pairing ble-thread 1 hex:<operationalDataset> 20202021 3840
+
+ chip-tool onoff on 1 1
+
+### Notes
+
+- Depending on your network settings your router might not provide native ipv6
+ addresses to your devices (Border router / PC). If this is the case, you
+ need to add a static ipv6 addresses on both device and then an ipv6 route to
+ the border router on your PC
+
+ - On Border Router: `sudo ip addr add dev <Network interface> 2002::2/64`
+
+ - On PC(Linux): `sudo ip addr add dev <Network interface> 2002::1/64`
+
+ - Add Ipv6 route on PC(Linux)
+ `sudo ip route add <Thread global ipv6 prefix>/64 via 2002::2`
+
+<a name="running-pigweed-rpc-console"></a>
+
+## Running RPC console
+
+- As part of building the example with RPCs enabled the chip_rpc python
+ interactive console is installed into your venv. The python wheel files are
+ also created in the output folder: out/debug/chip_rpc_console_wheels. To
+ install the wheel files without rebuilding:
+ `pip3 install out/debug/chip_rpc_console_wheels/*.whl`
+
+- To use the chip-rpc console after it has been installed run:
+ `chip-console --device /dev/tty.<SERIALDEVICE> -b 115200 -o /<YourFolder>/pw_log.out`
+
+- Then you can simulate a button press or release using the following command
+ where : idx = 0 or 1 for Button PB0 or PB1 action = 0 for PRESSED, 1 for
+ RELEASE Test toggling the LED with
+ `rpcs.chip.rpc.Button.Event(idx=1, pushed=True)`
+
+- You can also Get and Set the light directly using the RPCs:
+ `rpcs.chip.rpc.Lighting.Get()`
+
+ `rpcs.chip.rpc.Lighting.Set(on=True, level=128, color=protos.chip.rpc.LightingColor(hue=5, saturation=5))`
+
+## Device Tracing
+
+Device tracing is available to analyze the device performance. To turn on
+tracing, build with RPC enabled. See Build the example with pigweed RPC.
+
+Obtain tracing json file.
+
+ $ ./{PIGWEED_REPO}/pw_trace_tokenized/py/pw_trace_tokenized/get_trace.py -d {PORT} -o {OUTPUT_FILE} \
+ -t {ELF_FILE} {PIGWEED_REPO}/pw_trace_tokenized/pw_trace_protos/trace_rpc.proto
+
+## Memory settings
+
+While most of the RAM usage in CHIP is static, allowing easier debugging and
+optimization with symbols analysis, we still need some HEAP for the crypto and
+OpenThread. Size of the HEAP can be modified by changing the value of the
+`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this
+example. Please take note that a HEAP size smaller than 13k can and will cause a
+Mbedtls failure during the BLE rendez-vous or CASE session
+
+To track memory usage you can set `enable_heap_monitoring = true` either in the
+BUILD.gn file or pass it as a build argument to gn. This will print on the RTT
+console the RAM usage of each individual task and the number of Memory
+allocation and Free. While this is not extensive monitoring you're welcome to
+modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory
+tracking code inside the `trackAlloc` and `trackFree` function
+
+## OTA Software Update
+
+For the description of Software Update process with EFR32 example applications
+see
+[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md)
+
+## Group Communication (Multicast)
+
+With this lighting example you can also use group communication to send Lighting
+commands to multiples devices at once. Please refer to the
+[chip-tool documentation](../../chip-tool/README.md) _Configuring the server
+side for Group Commands_ and _Using the Client to Send Group (Multicast) Matter
+Commands_
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options to be
+passed to the build scripts.
+
+### Disabling logging
+
+`chip_progress_logging, chip_detail_logging, chip_automation_logging`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+
+### Debug build / release build
+
+`is_debug`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "is_debug=false"
+
+### Disabling LCD
+
+`show_qr_code`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false"
+
+### KVS maximum entry count
+
+`kvs_max_entries`
+
+ Set the maximum Kvs entries that can be stored in NVM (Default 75)
+ Thresholds: 30 <= kvs_max_entries <= 255
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50
diff --git a/examples/lighting-app/silabs/SiWx917/args.gni b/examples/lighting-app/silabs/SiWx917/args.gni
new file mode 100644
index 0000000..d216faa
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/args.gni
@@ -0,0 +1,30 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/platform/silabs/EFR32/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+
+pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip"
+pw_assert_BACKEND = "$dir_pw_assert_log:check_backend"
+chip_enable_openthread = true
+pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex"
+
+openthread_external_platform =
+ "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32"
diff --git a/examples/lighting-app/silabs/SiWx917/build_for_wifi_args.gni b/examples/lighting-app/silabs/SiWx917/build_for_wifi_args.gni
new file mode 100644
index 0000000..363d2be
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/build_for_wifi_args.gni
@@ -0,0 +1,25 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
+import("${chip_root}/config/standalone/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+chip_enable_openthread = false
+import("${chip_root}/src/platform/silabs/EFR32/wifi_args.gni")
+
+chip_enable_ota_requestor = true
+
+pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip"
+pw_assert_BACKEND = "$dir_pw_assert_log:check_backend"
diff --git a/examples/lighting-app/silabs/SiWx917/build_for_wifi_gnfile.gn b/examples/lighting-app/silabs/SiWx917/build_for_wifi_gnfile.gn
new file mode 100644
index 0000000..d391814
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/build_for_wifi_gnfile.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_enable_wifi = true
+ import("//build_for_wifi_args.gni")
+}
diff --git a/examples/lighting-app/silabs/SiWx917/build_overrides b/examples/lighting-app/silabs/SiWx917/build_overrides
new file mode 120000
index 0000000..995884e
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/build_overrides
@@ -0,0 +1 @@
+../../../build_overrides
\ No newline at end of file
diff --git a/examples/lighting-app/silabs/SiWx917/include/AppConfig.h b/examples/lighting-app/silabs/SiWx917/include/AppConfig.h
new file mode 100644
index 0000000..ffadaf9
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/AppConfig.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "efr32_utils.h"
+
+// ---- Lighting Example App Config ----
+
+#define APP_TASK_NAME "Lit"
+
+// Time it takes in ms for the simulated actuator to move from one
+// state to another.
+#define ACTUATOR_MOVEMENT_PERIOS_MS 10
diff --git a/examples/lighting-app/silabs/SiWx917/include/AppEvent.h b/examples/lighting-app/silabs/SiWx917/include/AppEvent.h
new file mode 100644
index 0000000..7a19b71
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/AppEvent.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2018 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_Button = 0,
+ kEventType_Timer,
+ kEventType_Light,
+ kEventType_Install,
+ };
+
+ uint16_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ uint8_t Action;
+ int32_t Actor;
+ } LightEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/examples/lighting-app/silabs/SiWx917/include/AppTask.h b/examples/lighting-app/silabs/SiWx917/include/AppTask.h
new file mode 100644
index 0000000..df80995
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/AppTask.h
@@ -0,0 +1,131 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+#include "BaseApplication.h"
+#include "FreeRTOS.h"
+#include "LightingManager.h"
+#include "sl_simple_button_instances.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app/clusters/identify-server/identify-server.h>
+#include <ble/BLEEndPoint.h>
+#include <lib/core/CHIPError.h>
+#include <platform/CHIPDeviceLayer.h>
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * AppTask Declaration
+ *********************************************************/
+
+class AppTask : public BaseApplication
+{
+
+public:
+ AppTask() = default;
+
+ static AppTask & GetAppTask() { return sAppTask; }
+
+ /**
+ * @brief AppTask task main loop function
+ *
+ * @param pvParameter FreeRTOS task parameter
+ */
+ static void AppTaskMain(void * pvParameter);
+
+ CHIP_ERROR StartAppTask();
+
+ /**
+ * @brief Event handler when a button is pressed
+ * Function posts an event for button processing
+ *
+ * @param buttonHandle APP_LIGHT_SWITCH or APP_FUNCTION_BUTTON
+ * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+ * SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+ */
+ void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction) override;
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is received
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStart(Identify * identify);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is stopped or finished
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStop(Identify * identify);
+
+ void PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction);
+
+private:
+ static AppTask sAppTask;
+
+ static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor);
+ static void ActionCompleted(LightingManager::Action_t aAction);
+ static void LightActionEventHandler(AppEvent * aEvent);
+
+ static void UpdateClusterState(intptr_t context);
+
+ /**
+ * @brief AppTask initialisation function
+ *
+ * @return CHIP_ERROR
+ */
+ CHIP_ERROR Init();
+
+ /**
+ * @brief PB0 Button event processing function
+ * Press and hold will trigger a factory reset timer start
+ * Press and release will restart BLEAdvertising if not commisionned
+ *
+ * @param aEvent button event being processed
+ */
+ static void ButtonHandler(AppEvent * aEvent);
+
+ /**
+ * @brief PB1 Button event processing function
+ * Function triggers a switch action sent to the CHIP task
+ *
+ * @param aEvent button event being processed
+ */
+ static void SwitchActionEventHandler(AppEvent * aEvent);
+};
diff --git a/examples/lighting-app/silabs/SiWx917/include/CHIPProjectConfig.h b/examples/lighting-app/silabs/SiWx917/include/CHIPProjectConfig.h
new file mode 100644
index 0000000..4b3d8f5
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/CHIPProjectConfig.h
@@ -0,0 +1,135 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+// WARNING: These options make it possible to circumvent basic Chip security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8005: example lighting app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
+ *
+ * The hardware version number assigned to device or product by the device vendor. This
+ * number is scoped to the device product id, and typically corresponds to a revision of the
+ * physical device, a change to its packaging, and/or a change to its marketing presentation.
+ * This value is generally *not* incremented for device software versions.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+ *
+ * A string identifying the software version running on the device.
+ * CHIP service currently expects the software version to be in the format
+ * {MAJOR_VERSION}.0d{MINOR_VERSION}
+ */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "0.1ALPHA"
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+ *
+ * A uint32_t identifying the software version running on the device.
+ */
+/* The SoftwareVersion attribute of the Basic cluster. */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x0001
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ * @brief
+ * Active retransmit interval, or time to wait before retransmission after
+ * subsequent failures in milliseconds.
+ *
+ * This is the default value, that might be adjusted by end device depending on its
+ * needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/examples/lighting-app/silabs/SiWx917/include/LightingManager.h b/examples/lighting-app/silabs/SiWx917/include/LightingManager.h
new file mode 100644
index 0000000..6d286fa
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/LightingManager.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app/clusters/on-off-server/on-off-server.h>
+
+#include <lib/core/CHIPError.h>
+
+class LightingManager
+{
+public:
+ enum Action_t
+ {
+ ON_ACTION = 0,
+ OFF_ACTION,
+
+ INVALID_ACTION
+ } Action;
+
+ enum State_t
+ {
+ kState_OffInitiated = 0,
+ kState_OffCompleted,
+ kState_OnInitiated,
+ kState_OnCompleted,
+ } State;
+
+ CHIP_ERROR Init();
+ bool IsLightOn();
+ void EnableAutoTurnOff(bool aOn);
+ void SetAutoTurnOffDuration(uint32_t aDurationInSecs);
+ bool IsActionInProgress();
+ bool InitiateAction(int32_t aActor, Action_t aAction);
+
+ typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor);
+ typedef void (*Callback_fn_completed)(Action_t);
+ void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);
+
+ static void OnTriggerOffWithEffect(OnOffEffect * effect);
+
+private:
+ friend LightingManager & LightMgr(void);
+ State_t mState;
+
+ Callback_fn_initiated mActionInitiated_CB;
+ Callback_fn_completed mActionCompleted_CB;
+
+ bool mAutoTurnOff;
+ uint32_t mAutoTurnOffDuration;
+ bool mAutoTurnOffTimerArmed;
+ bool mOffEffectArmed;
+
+ void CancelTimer(void);
+ void StartTimer(uint32_t aTimeoutMs);
+
+ static void TimerEventHandler(TimerHandle_t xTimer);
+ static void AutoTurnOffTimerEventHandler(AppEvent * aEvent);
+ static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
+ static void OffEffectTimerEventHandler(AppEvent * aEvent);
+
+ static LightingManager sLight;
+};
+
+inline LightingManager & LightMgr(void)
+{
+ return LightingManager::sLight;
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/AppTask.cpp b/examples/lighting-app/silabs/SiWx917/src/AppTask.cpp
new file mode 100644
index 0000000..850649d
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/AppTask.cpp
@@ -0,0 +1,333 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AppTask.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#include "sl_simple_led_instances.h"
+#endif // ENABLE_WSTK_LEDS
+
+#include <app-common/zap-generated/attribute-id.h>
+#include <app-common/zap-generated/attribute-type.h>
+#include <app-common/zap-generated/cluster-id.h>
+#include <app/clusters/identify-server/identify-server.h>
+#include <app/clusters/on-off-server/on-off-server.h>
+#include <app/server/OnboardingCodesUtil.h>
+#include <app/server/Server.h>
+#include <app/util/attribute-storage.h>
+
+#include <assert.h>
+
+#include <setup_payload/QRCodeSetupPayloadGenerator.h>
+#include <setup_payload/SetupPayload.h>
+
+#include <lib/support/CodeUtils.h>
+
+#include <platform/CHIPDeviceLayer.h>
+
+#ifdef ENABLE_WSTK_LEDS
+#define SYSTEM_STATE_LED &sl_led_led0
+#define LIGHT_LED &sl_led_led1
+#endif // ENABLE_WSTK_LEDS
+
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+#define APP_LIGHT_SWITCH &sl_button_btn1
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+#ifdef ENABLE_WSTK_LEDS
+LEDWidget sLightLED;
+#endif // ENABLE_WSTK_LEDS
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+/**********************************************************
+ * Identify Callbacks
+ *********************************************************/
+
+namespace {
+void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState)
+{
+ ChipLogProgress(Zcl, "Trigger Identify Complete");
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StopStatusLEDTimer();
+#endif
+}
+} // namespace
+
+void OnTriggerIdentifyEffect(Identify * identify)
+{
+ sIdentifyEffect = identify->mCurrentEffectIdentifier;
+
+ if (identify->mCurrentEffectIdentifier == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE)
+ {
+ ChipLogProgress(Zcl, "IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE - Not supported, use effect varriant %d",
+ identify->mEffectVariant);
+ sIdentifyEffect = static_cast<EmberAfIdentifyEffectIdentifier>(identify->mEffectVariant);
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StartStatusLEDTimer();
+#endif
+
+ switch (sIdentifyEffect)
+ {
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+ break;
+ default:
+ ChipLogProgress(Zcl, "No identifier effect");
+ }
+}
+
+Identify gIdentify = {
+ chip::EndpointId{ 1 },
+ AppTask::GetAppTask().OnIdentifyStart,
+ AppTask::GetAppTask().OnIdentifyStop,
+ EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED,
+ OnTriggerIdentifyEffect,
+};
+
+} // namespace
+
+using namespace chip::TLV;
+using namespace ::chip::DeviceLayer;
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+#ifdef DISPLAY_ENABLED
+ GetLCD().Init((uint8_t *) "Lighting-App");
+#endif
+
+ err = BaseApplication::Init(&gIdentify);
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("BaseApplication::Init() failed");
+ appError(err);
+ }
+
+ err = LightMgr().Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("LightMgr::Init() failed");
+ appError(err);
+ }
+
+ LightMgr().SetCallbacks(ActionInitiated, ActionCompleted);
+
+#ifdef ENABLE_WSTK_LEDS
+ sLightLED.Init(LIGHT_LED);
+ sLightLED.Set(LightMgr().IsLightOn());
+#endif // ENABLE_WSTK_LEDS
+
+ return err;
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ return BaseApplication::StartAppTask(AppTaskMain);
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+ QueueHandle_t sAppEventQueue = *(static_cast<QueueHandle_t *>(pvParameter));
+
+ CHIP_ERROR err = sAppTask.Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("AppTask.Init() failed");
+ appError(err);
+ }
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+ sAppTask.StartStatusLEDTimer();
+#endif
+
+ SILABS_LOG("App Task started");
+
+ while (true)
+ {
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, pdMS_TO_TICKS(10));
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+ }
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStart");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StartStatusLEDTimer();
+#endif
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStop");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StopStatusLEDTimer();
+#endif
+}
+
+void AppTask::LightActionEventHandler(AppEvent * aEvent)
+{
+ bool initiated = false;
+ LightingManager::Action_t action;
+ int32_t actor;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (aEvent->Type == AppEvent::kEventType_Light)
+ {
+ action = static_cast<LightingManager::Action_t>(aEvent->LightEvent.Action);
+ actor = aEvent->LightEvent.Actor;
+ }
+ else if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ action = (LightMgr().IsLightOn()) ? LightingManager::OFF_ACTION : LightingManager::ON_ACTION;
+ actor = AppEvent::kEventType_Button;
+ }
+ else
+ {
+ err = APP_ERROR_UNHANDLED_EVENT;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ initiated = LightMgr().InitiateAction(actor, action);
+
+ if (!initiated)
+ {
+ SILABS_LOG("Action is already in progress or active.");
+ }
+ }
+}
+
+void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction)
+{
+ if (buttonHandle == NULL)
+ {
+ return;
+ }
+
+ AppEvent button_event = {};
+ button_event.Type = AppEvent::kEventType_Button;
+ button_event.ButtonEvent.Action = btnAction;
+
+ if (buttonHandle == APP_LIGHT_SWITCH && btnAction == SL_SIMPLE_BUTTON_PRESSED)
+ {
+ button_event.Handler = LightActionEventHandler;
+ sAppTask.PostEvent(&button_event);
+ }
+ else if (buttonHandle == APP_FUNCTION_BUTTON)
+ {
+ button_event.Handler = BaseApplication::ButtonHandler;
+ sAppTask.PostEvent(&button_event);
+ }
+}
+
+void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor)
+{
+ // Action initiated, update the light led
+ bool lightOn = aAction == LightingManager::ON_ACTION;
+ SILABS_LOG("Turning light %s", (lightOn) ? "On" : "Off")
+
+#ifdef ENABLE_WSTK_LEDS
+ sLightLED.Set(lightOn);
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+ sAppTask.GetLCD().WriteDemoUI(lightOn);
+#endif
+
+ if (aActor == AppEvent::kEventType_Button)
+ {
+ sAppTask.mSyncClusterToButtonAction = true;
+ }
+}
+
+void AppTask::ActionCompleted(LightingManager::Action_t aAction)
+{
+ // action has been completed bon the light
+ if (aAction == LightingManager::ON_ACTION)
+ {
+ SILABS_LOG("Light ON")
+ }
+ else if (aAction == LightingManager::OFF_ACTION)
+ {
+ SILABS_LOG("Light OFF")
+ }
+
+ if (sAppTask.mSyncClusterToButtonAction)
+ {
+ chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast<intptr_t>(nullptr));
+ sAppTask.mSyncClusterToButtonAction = false;
+ }
+}
+
+void AppTask::PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Light;
+ event.LightEvent.Actor = aActor;
+ event.LightEvent.Action = aAction;
+ event.Handler = LightActionEventHandler;
+ PostEvent(&event);
+}
+
+void AppTask::UpdateClusterState(intptr_t context)
+{
+ uint8_t newValue = LightMgr().IsLightOn();
+
+ // write the new on/off value
+ EmberAfStatus status = OnOffServer::Instance().setOnOffValue(1, newValue, false);
+
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ SILABS_LOG("ERR: updating on/off %x", status);
+ }
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/LightingManager.cpp b/examples/lighting-app/silabs/SiWx917/src/LightingManager.cpp
new file mode 100644
index 0000000..31a4ca0
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/LightingManager.cpp
@@ -0,0 +1,322 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LightingManager.h"
+
+#include "AppConfig.h"
+#include "AppTask.h"
+#include <FreeRTOS.h>
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+LightingManager LightingManager::sLight;
+
+TimerHandle_t sLightTimer;
+
+namespace {
+
+/**********************************************************
+ * OffWithEffect Callbacks
+ *********************************************************/
+
+OnOffEffect gEffect = {
+ chip::EndpointId{ 1 },
+ LightMgr().OnTriggerOffWithEffect,
+ EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF,
+ static_cast<uint8_t>(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS),
+};
+
+} // namespace
+
+CHIP_ERROR LightingManager::Init()
+{
+ // Create FreeRTOS sw timer for light timer.
+ sLightTimer = xTimerCreate("lightTmr", // Just a text name, not used by the RTOS kernel
+ 1, // == default timer period (mS)
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = light obj context
+ TimerEventHandler // timer callback handler
+ );
+
+ if (sLightTimer == NULL)
+ {
+ SILABS_LOG("sLightTimer timer create failed");
+ return APP_ERROR_CREATE_TIMER_FAILED;
+ }
+
+ bool currentLedState;
+ // read current on/off value on endpoint one.
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ OnOffServer::Instance().getOnOffValue(1, ¤tLedState);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ mState = currentLedState ? kState_OnCompleted : kState_OffCompleted;
+ mAutoTurnOffTimerArmed = false;
+ mAutoTurnOff = false;
+ mAutoTurnOffDuration = 0;
+ mOffEffectArmed = false;
+
+ return CHIP_NO_ERROR;
+}
+
+void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
+{
+ mActionInitiated_CB = aActionInitiated_CB;
+ mActionCompleted_CB = aActionCompleted_CB;
+}
+
+bool LightingManager::IsActionInProgress()
+{
+ return (mState == kState_OffInitiated || mState == kState_OnInitiated);
+}
+
+bool LightingManager::IsLightOn()
+{
+ return (mState == kState_OnCompleted);
+}
+
+void LightingManager::EnableAutoTurnOff(bool aOn)
+{
+ mAutoTurnOff = aOn;
+}
+
+void LightingManager::SetAutoTurnOffDuration(uint32_t aDurationInSecs)
+{
+ mAutoTurnOffDuration = aDurationInSecs;
+}
+
+bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
+{
+ bool action_initiated = false;
+ State_t new_state;
+
+ // Initiate Turn On/Off Action only when the previous one is complete.
+ if (((mState == kState_OffCompleted) || mOffEffectArmed) && aAction == ON_ACTION)
+ {
+ action_initiated = true;
+
+ new_state = kState_OnInitiated;
+ }
+ else if (mState == kState_OnCompleted && aAction == OFF_ACTION && mOffEffectArmed == false)
+ {
+ action_initiated = true;
+
+ new_state = kState_OffInitiated;
+ }
+
+ if (action_initiated)
+ {
+ if (mAutoTurnOffTimerArmed && new_state == kState_OffInitiated)
+ {
+ // If auto turn off timer has been armed and someone initiates turning off,
+ // cancel the timer and continue as normal.
+ mAutoTurnOffTimerArmed = false;
+
+ CancelTimer();
+ }
+
+ if (mOffEffectArmed && new_state == kState_OnInitiated)
+ {
+ CancelTimer();
+ mOffEffectArmed = false;
+ }
+
+ StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
+
+ // Since the timer started successfully, update the state and trigger callback
+ mState = new_state;
+
+ if (mActionInitiated_CB)
+ {
+ mActionInitiated_CB(aAction, aActor);
+ }
+ }
+
+ return action_initiated;
+}
+
+void LightingManager::StartTimer(uint32_t aTimeoutMs)
+{
+ if (xTimerIsTimerActive(sLightTimer))
+ {
+ SILABS_LOG("app timer already started!");
+ CancelTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ticks if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sLightTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS)
+ {
+ SILABS_LOG("sLightTimer timer start() failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+}
+
+void LightingManager::CancelTimer(void)
+{
+ if (xTimerStop(sLightTimer, 0) == pdFAIL)
+ {
+ SILABS_LOG("sLightTimer stop() failed");
+ appError(APP_ERROR_STOP_TIMER_FAILED);
+ }
+}
+
+void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
+{
+ // Get light obj context from timer id.
+ LightingManager * light = static_cast<LightingManager *>(pvTimerGetTimerID(xTimer));
+
+ // The timer event handler will be called in the context of the timer task
+ // once sLightTimer expires. Post an event to apptask queue with the actual handler
+ // so that the event can be handled in the context of the apptask.
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = light;
+ if (light->mAutoTurnOffTimerArmed)
+ {
+ event.Handler = AutoTurnOffTimerEventHandler;
+ }
+ else if (light->mOffEffectArmed)
+ {
+ event.Handler = OffEffectTimerEventHandler;
+ }
+ else
+ {
+ event.Handler = ActuatorMovementTimerEventHandler;
+ }
+ AppTask::GetAppTask().PostEvent(&event);
+}
+
+void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
+{
+ LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
+ int32_t actor = AppEvent::kEventType_Timer;
+
+ // Make sure auto turn off timer is still armed.
+ if (!light->mAutoTurnOffTimerArmed)
+ {
+ return;
+ }
+
+ light->mAutoTurnOffTimerArmed = false;
+
+ SILABS_LOG("Auto Turn Off has been triggered!");
+
+ light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent)
+{
+ LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
+ int32_t actor = AppEvent::kEventType_Timer;
+
+ // Make sure auto turn off timer is still armed.
+ if (!light->mOffEffectArmed)
+ {
+ return;
+ }
+
+ light->mOffEffectArmed = false;
+
+ SILABS_LOG("OffEffect completed");
+
+ light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
+{
+ Action_t actionCompleted = INVALID_ACTION;
+
+ LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
+
+ if (light->mState == kState_OffInitiated)
+ {
+ light->mState = kState_OffCompleted;
+ actionCompleted = OFF_ACTION;
+ }
+ else if (light->mState == kState_OnInitiated)
+ {
+ light->mState = kState_OnCompleted;
+ actionCompleted = ON_ACTION;
+ }
+
+ if (actionCompleted != INVALID_ACTION)
+ {
+ if (light->mActionCompleted_CB)
+ {
+ light->mActionCompleted_CB(actionCompleted);
+ }
+
+ if (light->mAutoTurnOff && actionCompleted == ON_ACTION)
+ {
+ // Start the timer for auto turn off
+ light->StartTimer(light->mAutoTurnOffDuration * 1000);
+
+ light->mAutoTurnOffTimerArmed = true;
+
+ SILABS_LOG("Auto Turn off enabled. Will be triggered in %u seconds", light->mAutoTurnOffDuration);
+ }
+ }
+}
+
+void LightingManager::OnTriggerOffWithEffect(OnOffEffect * effect)
+{
+ chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier;
+ uint8_t effectVariant = effect->mEffectVariant;
+ uint32_t offEffectDuration = 0;
+
+ // Temporary print outs and delay to test OffEffect behaviour
+ // Until dimming is supported for dev boards.
+ if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF)
+ {
+ if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS)
+ {
+ offEffectDuration = 800;
+ ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS");
+ }
+ else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE)
+ {
+ offEffectDuration = 800;
+ ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE");
+ }
+ else if (effectVariant ==
+ EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS)
+ {
+ offEffectDuration = 12800;
+ ChipLogProgress(Zcl,
+ "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_"
+ "IN_12_SECONDS");
+ }
+ }
+ else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT)
+ {
+ if (effectVariant ==
+ EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND)
+ {
+ offEffectDuration = 1500;
+ ChipLogProgress(
+ Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND");
+ }
+ }
+
+ LightMgr().mOffEffectArmed = true;
+ LightMgr().StartTimer(offEffectDuration);
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/ZclCallbacks.cpp b/examples/lighting-app/silabs/SiWx917/src/ZclCallbacks.cpp
new file mode 100644
index 0000000..cfbcbc8
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/ZclCallbacks.cpp
@@ -0,0 +1,91 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * This file implements the handler for data model messages.
+ */
+
+#include "AppConfig.h"
+#include "LightingManager.h"
+
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/ConcreteAttributePath.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+using namespace ::chip;
+using namespace ::chip::app::Clusters;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+ uint8_t * value)
+{
+ ClusterId clusterId = attributePath.mClusterId;
+ AttributeId attributeId = attributePath.mAttributeId;
+ ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
+
+ if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
+ {
+ LightMgr().InitiateAction(AppEvent::kEventType_Light, *value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION);
+ }
+ else if (clusterId == LevelControl::Id)
+ {
+ ChipLogProgress(Zcl, "Level Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == ColorControl::Id)
+ {
+ ChipLogProgress(Zcl, "Color Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == OnOffSwitchConfiguration::Id)
+ {
+ ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == Identify::Id)
+ {
+ ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+ }
+}
+
+/** @brief OnOff Cluster Init
+ *
+ * This function is called when a specific cluster is initialized. It gives the
+ * application an opportunity to take care of cluster initialization procedures.
+ * It is called exactly once for each endpoint where cluster is present.
+ *
+ * @param endpoint Ver.: always
+ *
+ * TODO Issue #3841
+ * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster
+ * attributes to the default value.
+ * The logic here expects something similar to the deprecated Plugins callback
+ * emberAfPluginOnOffClusterServerPostInitCallback.
+ *
+ */
+void emberAfOnOffClusterInitCallback(EndpointId endpoint)
+{
+ // TODO: implement any additional Cluster Server init actions
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/main.cpp b/examples/lighting-app/silabs/SiWx917/src/main.cpp
new file mode 100644
index 0000000..2594f6f
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/main.cpp
@@ -0,0 +1,84 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <AppTask.h>
+
+#include "AppConfig.h"
+#include "init_efrPlatform.h"
+#include "sl_simple_button_instances.h"
+#include "sl_system_kernel.h"
+#include <DeviceInfoProviderImpl.h>
+#include <app/server/Server.h>
+#include <credentials/DeviceAttestationCredsProvider.h>
+#include <matter_config.h>
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+#include <examples/platform/silabs/SilabsDeviceAttestationCreds.h>
+#else
+#include <credentials/examples/DeviceAttestationCredsExample.h>
+#endif
+
+#define BLE_DEV_NAME "SiLabs-Light"
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Credentials;
+
+#define UNUSED_PARAMETER(a) (a = a)
+
+volatile int apperror_cnt;
+static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+
+// ================================================================================
+// Main Code
+// ================================================================================
+int main(void)
+{
+ init_efrPlatform();
+ if (EFR32MatterConfig::InitMatter(BLE_DEV_NAME) != CHIP_NO_ERROR)
+ appError(CHIP_ERROR_INTERNAL);
+
+ gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage());
+ chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ // Initialize device attestation config
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+ SetDeviceAttestationCredentialsProvider(Silabs::GetSilabsDacProvider());
+#else
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ SILABS_LOG("Starting App Task");
+ if (AppTask::GetAppTask().StartAppTask() != CHIP_NO_ERROR)
+ appError(CHIP_ERROR_INTERNAL);
+
+ SILABS_LOG("Starting FreeRTOS scheduler");
+ sl_system_kernel_start();
+
+ // Should never get here.
+ chip::Platform::MemoryShutdown();
+ SILABS_LOG("vTaskStartScheduler() failed");
+ appError(CHIP_ERROR_INTERNAL);
+}
+
+void sl_button_on_change(const sl_button_t * handle)
+{
+ AppTask::GetAppTask().ButtonEventHandler(handle, sl_button_get_state(handle));
+}
diff --git a/examples/lighting-app/silabs/SiWx917/third_party/connectedhomeip b/examples/lighting-app/silabs/SiWx917/third_party/connectedhomeip
new file mode 120000
index 0000000..5930783
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../..
\ No newline at end of file
diff --git a/examples/lighting-app/silabs/SiWx917/with_pw_rpc.gni b/examples/lighting-app/silabs/SiWx917/with_pw_rpc.gni
new file mode 100644
index 0000000..40a8bb7
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/with_pw_rpc.gni
@@ -0,0 +1,31 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# add this gni as import in your build args to use pigweed in the example
+# 'import("//with_pw_rpc.gni")'
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni")
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_pw_rpc = true
+chip_enable_openthread = true
+chip_build_pw_trace_lib = true
+
+cpp_standard = "gnu++17"
+
+# Light app on EFR enables tracing server
+pw_trace_BACKEND = "$dir_pw_trace_tokenized"
diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn
new file mode 100644
index 0000000..dbd8473
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,110 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("${chip_root}/src/lib/lib.gni")
+import("${chip_root}/src/platform/device.gni")
+import("${efr32_sdk_build_root}/efr32_sdk.gni")
+
+config("chip_examples_project_config") {
+ include_dirs = [ "project_include" ]
+
+ # Link options that provide a replacement for dynamic memory operations in standard
+ # library with the FreeRTOS malloc in platform code.
+ ldflags = [
+ # memory allocation -- these must be re-entrant and do locking
+ "-Wl,--wrap=malloc",
+ "-Wl,--wrap=free",
+ "-Wl,--wrap=realloc",
+ "-Wl,--wrap=calloc",
+ "-Wl,--wrap=MemoryAlloc",
+
+ # Wrap these in case internal newlib call them (e.g. strdup will)
+ # directly call _malloc_r)
+ "-Wl,--wrap=_malloc_r",
+ "-Wl,--wrap=_realloc_r",
+ "-Wl,--wrap=_free_r",
+ "-Wl,--wrap=_calloc_r",
+ ]
+}
+
+source_set("openthread_core_config_efr32_chip_examples") {
+ if (chip_enable_openthread) {
+ sources = [ "project_include/OpenThreadConfig.h" ]
+
+ public_deps = [ "${efr32_sdk_build_root}:efr32_sdk" ]
+
+ if (use_silabs_thread_lib) {
+ public_deps += [ "${efr32_sdk_build_root}:openthread_core_config_efr32" ]
+ } else {
+ public_deps += [ "${chip_root}/third_party/openthread/platforms/efr32:openthread_core_config_efr32" ]
+ }
+
+ public_configs = [ ":chip_examples_project_config" ]
+ }
+}
+
+source_set("efr-matter-shell") {
+ if (chip_build_libshell) {
+ defines = [ "ENABLE_CHIP_SHELL" ]
+
+ sources = [ "matter_shell.cpp" ]
+ include_dirs = [ "." ]
+
+ public_deps = [
+ "${chip_root}/examples/shell/shell_common:shell_common",
+ "${chip_root}/src/lib/shell:shell",
+ "${chip_root}/src/lib/shell:shell_core",
+ ]
+ }
+}
+
+config("attestation-credentials-config") {
+ include_dirs = [ "${chip_root}" ]
+
+ defines = [
+ # Set to 1 to enable EFR32 attestation credentials
+ "EFR32_ATTESTATION_CREDENTIALS",
+ ]
+}
+
+source_set("efr32-attestation-credentials") {
+ sources = [
+ "../SilabsDeviceAttestationCreds.cpp",
+ "../SilabsDeviceAttestationCreds.h",
+ ]
+
+ public_deps = [
+ "${chip_root}/src/credentials",
+ "${chip_root}/src/platform:platform_base",
+ ]
+
+ public_configs = [ ":attestation-credentials-config" ]
+}
+
+source_set("efr32-factory-data-provider") {
+ sources = [
+ "EFR32DeviceDataProvider.cpp",
+ "EFR32DeviceDataProvider.h",
+ ]
+
+ public_deps = [
+ "${chip_root}/src/credentials",
+ "${chip_root}/src/platform:platform_base",
+ "${chip_root}/src/setup_payload",
+ ]
+
+ #public_configs = [ "" ]
+}
diff --git a/examples/platform/silabs/SiWx917/BaseApplication.cpp b/examples/platform/silabs/SiWx917/BaseApplication.cpp
new file mode 100644
index 0000000..85748b3
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/BaseApplication.cpp
@@ -0,0 +1,571 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#include "sl_simple_led_instances.h"
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+#include "lcd.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+
+#include "EFR32DeviceDataProvider.h"
+#include <app-common/zap-generated/attribute-id.h>
+#include <app-common/zap-generated/attribute-type.h>
+#include <app-common/zap-generated/cluster-id.h>
+#include <app/server/OnboardingCodesUtil.h>
+#include <app/server/Server.h>
+#include <app/util/attribute-storage.h>
+#include <assert.h>
+#include <lib/support/CodeUtils.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <setup_payload/QRCodeSetupPayloadGenerator.h>
+#include <setup_payload/SetupPayload.h>
+
+#if CHIP_ENABLE_OPENTHREAD
+#include <platform/OpenThread/OpenThreadUtils.h>
+#include <platform/ThreadStackManager.h>
+#include <platform/silabs/ThreadStackManagerImpl.h>
+#endif // CHIP_ENABLE_OPENTHREAD
+
+#ifdef SL_WIFI
+#include "wfx_host_events.h"
+#include <app/clusters/network-commissioning/network-commissioning.h>
+#include <platform/silabs/NetworkCommissioningWiFiDriver.h>
+#endif // SL_WIFI
+
+/**********************************************************
+ * Defines and Constants
+ *********************************************************/
+
+#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
+#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
+#ifndef APP_TASK_STACK_SIZE
+#define APP_TASK_STACK_SIZE (4096)
+#endif
+#define APP_TASK_PRIORITY 2
+#define APP_EVENT_QUEUE_SIZE 10
+#define EXAMPLE_VENDOR_ID 0xcafe
+
+#ifdef ENABLE_WSTK_LEDS
+#define SYSTEM_STATE_LED &sl_led_led0
+#endif // ENABLE_WSTK_LEDS
+
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+/**********************************************************
+ * Variable declarations
+ *********************************************************/
+
+TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer.
+TimerHandle_t sLightTimer;
+
+TaskHandle_t sAppTaskHandle;
+QueueHandle_t sAppEventQueue;
+
+#ifdef ENABLE_WSTK_LEDS
+LEDWidget sStatusLED;
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef SL_WIFI
+app::Clusters::NetworkCommissioning::Instance
+ sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::SlWiFiDriver::GetInstance()));
+#endif /* SL_WIFI */
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+
+bool sIsProvisioned = false;
+bool sIsEnabled = false;
+bool sIsAttached = false;
+bool sHaveBLEConnections = false;
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+uint8_t sAppEventQueueBuffer[APP_EVENT_QUEUE_SIZE * sizeof(AppEvent)];
+StaticQueue_t sAppEventQueueStruct;
+
+StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)];
+StaticTask_t appTaskStruct;
+
+BaseApplication::Function_t mFunction;
+bool mFunctionTimerActive;
+
+Identify * gIdentifyptr = nullptr;
+
+#ifdef DISPLAY_ENABLED
+SilabsLCD slLCD;
+#endif
+
+} // namespace
+
+/**********************************************************
+ * AppTask Definitions
+ *********************************************************/
+
+CHIP_ERROR BaseApplication::StartAppTask(TaskFunction_t taskFunction)
+{
+ sAppEventQueue = xQueueCreateStatic(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent), sAppEventQueueBuffer, &sAppEventQueueStruct);
+ if (sAppEventQueue == NULL)
+ {
+ SILABS_LOG("Failed to allocate app event queue");
+ appError(APP_ERROR_EVENT_QUEUE_FAILED);
+ }
+
+ // Start App task.
+ sAppTaskHandle =
+ xTaskCreateStatic(taskFunction, APP_TASK_NAME, ArraySize(appStack), &sAppEventQueue, 1, appStack, &appTaskStruct);
+ if (sAppTaskHandle == nullptr)
+ {
+ SILABS_LOG("Failed to create app task");
+ appError(APP_ERROR_CREATE_TASK_FAILED);
+ }
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BaseApplication::Init(Identify * identifyObj)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (identifyObj == nullptr)
+ {
+ SILABS_LOG("Invalid Identify Object!");
+ appError(CHIP_ERROR_INVALID_ARGUMENT);
+ }
+
+ gIdentifyptr = identifyObj;
+
+#ifdef SL_WIFI
+ /*
+ * Wait for the WiFi to be initialized
+ */
+ SILABS_LOG("APP: Wait WiFi Init");
+ while (!wfx_hw_ready())
+ {
+ vTaskDelay(10);
+ }
+ SILABS_LOG("APP: Done WiFi Init");
+ /* We will init server when we get IP */
+
+ sWiFiNetworkCommissioningInstance.Init();
+#endif
+
+ // Create FreeRTOS sw timer for Function Selection.
+ sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel
+ 1, // == default timer period (mS)
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = app task obj context
+ FunctionTimerEventHandler // timer callback handler
+ );
+ if (sFunctionTimer == NULL)
+ {
+ SILABS_LOG("funct timer create failed");
+ appError(APP_ERROR_CREATE_TIMER_FAILED);
+ }
+
+ // Create FreeRTOS sw timer for LED Management.
+ sLightTimer = xTimerCreate("LightTmr", // Text Name
+ 10, // Default timer period (mS)
+ true, // reload timer
+ (void *) this, // Timer Id
+ LightTimerEventHandler // Timer callback handler
+ );
+ if (sLightTimer == NULL)
+ {
+ SILABS_LOG("Light Timer create failed");
+ appError(APP_ERROR_CREATE_TIMER_FAILED);
+ }
+
+ SILABS_LOG("Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
+
+#ifdef ENABLE_WSTK_LEDS
+ LEDWidget::InitGpio();
+ sStatusLED.Init(SYSTEM_STATE_LED);
+#endif // ENABLE_WSTK_LEDS
+
+ ConfigurationMgr().LogDeviceConfig();
+
+ // Create buffer for QR code that can fit max size and null terminator.
+ char qrCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
+ chip::MutableCharSpan QRCode(qrCodeBuffer);
+
+ if (EFR32::EFR32DeviceDataProvider::GetDeviceDataProvider().GetSetupPayload(QRCode) == CHIP_NO_ERROR)
+ {
+ // Print setup info on LCD if available
+#ifdef QR_CODE_ENABLED
+ slLCD.SetQRCode((uint8_t *) QRCode.data(), QRCode.size());
+ slLCD.ShowQRCode(true, true);
+#else
+ PrintQrCodeURL(QRCode);
+#endif // QR_CODE_ENABLED
+ }
+ else
+ {
+ SILABS_LOG("Getting QR code failed!");
+ }
+
+ return err;
+}
+
+void BaseApplication::FunctionTimerEventHandler(TimerHandle_t xTimer)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = (void *) xTimer;
+ event.Handler = FunctionEventHandler;
+ PostEvent(&event);
+}
+
+void BaseApplication::FunctionEventHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type != AppEvent::kEventType_Timer)
+ {
+ return;
+ }
+
+ // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT,
+ // initiate factory reset
+ if (mFunctionTimerActive && mFunction == kFunction_StartBleAdv)
+ {
+ SILABS_LOG("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
+
+ // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to
+ // cancel, if required.
+ StartFunctionTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ StartStatusLEDTimer();
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+ mFunction = kFunction_FactoryReset;
+
+#ifdef ENABLE_WSTK_LEDS
+ // Turn off all LEDs before starting blink to make sure blink is
+ // co-ordinated.
+ sStatusLED.Set(false);
+ sStatusLED.Blink(500);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else if (mFunctionTimerActive && mFunction == kFunction_FactoryReset)
+ {
+ // Actually trigger Factory Reset
+ mFunction = kFunction_NoneSelected;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ StopStatusLEDTimer();
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+ chip::Server::GetInstance().ScheduleFactoryReset();
+ }
+}
+
+void BaseApplication::LightEventHandler()
+{
+ // Collect connectivity and configuration state from the CHIP stack. Because
+ // the CHIP event loop is being run in a separate task, the stack must be
+ // locked while these values are queried. However we use a non-blocking
+ // lock request (TryLockCHIPStack()) to avoid blocking other UI activities
+ // when the CHIP task is busy (e.g. with a long crypto operation).
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+ if (PlatformMgr().TryLockChipStack())
+ {
+#ifdef SL_WIFI
+ sIsProvisioned = ConnectivityMgr().IsWiFiStationProvisioned();
+ sIsEnabled = ConnectivityMgr().IsWiFiStationEnabled();
+ sIsAttached = ConnectivityMgr().IsWiFiStationConnected();
+#endif /* SL_WIFI */
+#if CHIP_ENABLE_OPENTHREAD
+ sIsProvisioned = ConnectivityMgr().IsThreadProvisioned();
+ sIsEnabled = ConnectivityMgr().IsThreadEnabled();
+ sIsAttached = ConnectivityMgr().IsThreadAttached();
+#endif /* CHIP_ENABLE_OPENTHREAD */
+ sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0);
+ PlatformMgr().UnlockChipStack();
+ }
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+ // Update the status LED if factory reset has not been initiated.
+ //
+ // If system has "full connectivity", keep the LED On constantly.
+ //
+ // If thread and service provisioned, but not attached to the thread network
+ // yet OR no connectivity to the service OR subscriptions are not fully
+ // established THEN blink the LED Off for a short period of time.
+ //
+ // If the system has ble connection(s) uptill the stage above, THEN blink
+ // the LEDs at an even rate of 100ms.
+ //
+ // Otherwise, blink the LED ON for a very short time.
+ if (mFunction != kFunction_FactoryReset)
+ {
+ if ((gIdentifyptr != nullptr) && (gIdentifyptr->mActive))
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Blink(250, 250);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else if (sIdentifyEffect != EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT)
+ {
+ if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Blink(50, 50);
+#endif // ENABLE_WSTK_LEDS
+ }
+ if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Blink(1000, 1000);
+#endif // ENABLE_WSTK_LEDS
+ }
+ if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Blink(300, 700);
+#endif // ENABLE_WSTK_LEDS
+ }
+ }
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+ else if (sIsProvisioned && sIsEnabled)
+ {
+ if (sIsAttached)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Set(true);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Blink(950, 50);
+#endif
+ }
+ }
+ else if (sHaveBLEConnections)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Blink(100, 100);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else
+ {
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Blink(50, 950);
+#endif // ENABLE_WSTK_LEDS
+ }
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+ }
+
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Animate();
+#endif // ENABLE_WSTK_LEDS
+}
+
+void BaseApplication::ButtonHandler(AppEvent * aEvent)
+{
+ // To trigger software update: press the APP_FUNCTION_BUTTON button briefly (<
+ // FACTORY_RESET_TRIGGER_TIMEOUT) To initiate factory reset: press the
+ // APP_FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT +
+ // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT All LEDs start blinking after
+ // FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
+ // To cancel factory reset: release the APP_FUNCTION_BUTTON once all LEDs
+ // start blinking within the FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
+ if (aEvent->ButtonEvent.Action == SL_SIMPLE_BUTTON_PRESSED)
+ {
+ if (!mFunctionTimerActive && mFunction == kFunction_NoneSelected)
+ {
+ StartFunctionTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+ mFunction = kFunction_StartBleAdv;
+ }
+ }
+ else
+ {
+ // If the button was released before factory reset got initiated, open the commissioning window and start BLE advertissement
+ // in fast mode
+ if (mFunctionTimerActive && mFunction == kFunction_StartBleAdv)
+ {
+ CancelFunctionTimer();
+ mFunction = kFunction_NoneSelected;
+
+#ifdef QR_CODE_ENABLED
+ // TOGGLE QRCode/LCD demo UI
+ slLCD.ToggleQRCode();
+#endif
+
+#ifdef SL_WIFI
+ if (!ConnectivityMgr().IsWiFiStationProvisioned())
+#else
+ if (!ConnectivityMgr().IsThreadProvisioned())
+#endif /* !SL_WIFI */
+ {
+ // Open Basic CommissioningWindow. Will start BLE advertisements
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ CHIP_ERROR err = chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow();
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("Failed to open the Basic Commissioning Window");
+ }
+ }
+ else { SILABS_LOG("Network is already provisioned, Ble advertissement not enabled"); }
+ }
+ else if (mFunctionTimerActive && mFunction == kFunction_FactoryReset)
+ {
+ CancelFunctionTimer();
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ StopStatusLEDTimer();
+#endif
+
+ // Change the function to none selected since factory reset has been
+ // canceled.
+ mFunction = kFunction_NoneSelected;
+ SILABS_LOG("Factory Reset has been Canceled");
+ }
+ }
+}
+
+void BaseApplication::CancelFunctionTimer()
+{
+ if (xTimerStop(sFunctionTimer, 0) == pdFAIL)
+ {
+ SILABS_LOG("app timer stop() failed");
+ appError(APP_ERROR_STOP_TIMER_FAILED);
+ }
+
+ mFunctionTimerActive = false;
+}
+
+void BaseApplication::StartFunctionTimer(uint32_t aTimeoutInMs)
+{
+ if (xTimerIsTimerActive(sFunctionTimer))
+ {
+ SILABS_LOG("app timer already started!");
+ CancelFunctionTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ticks if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
+ {
+ SILABS_LOG("app timer start() failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+
+ mFunctionTimerActive = true;
+}
+
+void BaseApplication::StartStatusLEDTimer()
+{
+ if (pdPASS != xTimerStart(sLightTimer, 0))
+ {
+ SILABS_LOG("Light Time start failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+}
+
+void BaseApplication::StopStatusLEDTimer()
+{
+#ifdef ENABLE_WSTK_LEDS
+ sStatusLED.Set(false);
+#endif // ENABLE_WSTK_LEDS
+
+ if (xTimerStop(sLightTimer, 100) != pdPASS)
+ {
+ SILABS_LOG("Light Time start failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+}
+
+void BaseApplication::LightTimerEventHandler(TimerHandle_t xTimer)
+{
+ LightEventHandler();
+}
+
+#ifdef DISPLAY_ENABLED
+SilabsLCD & BaseApplication::GetLCD(void)
+{
+ return slLCD;
+}
+#endif
+
+void BaseApplication::PostEvent(const AppEvent * aEvent)
+{
+ if (sAppEventQueue != NULL)
+ {
+ BaseType_t status;
+ if (xPortIsInsideInterrupt())
+ {
+ BaseType_t higherPrioTaskWoken = pdFALSE;
+ status = xQueueSendFromISR(sAppEventQueue, aEvent, &higherPrioTaskWoken);
+
+#ifdef portYIELD_FROM_ISR
+ portYIELD_FROM_ISR(higherPrioTaskWoken);
+#elif portEND_SWITCHING_ISR // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+ portEND_SWITCHING_ISR(higherPrioTaskWoken);
+#else // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+#error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR"
+#endif // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+ }
+ else
+ {
+ status = xQueueSend(sAppEventQueue, aEvent, 1);
+ }
+
+ if (!status)
+ {
+ SILABS_LOG("Failed to post event to app task event queue");
+ }
+ }
+ else
+ {
+ SILABS_LOG("Event Queue is NULL should never happen");
+ }
+}
+
+void BaseApplication::DispatchEvent(AppEvent * aEvent)
+{
+ if (aEvent->Handler)
+ {
+ aEvent->Handler(aEvent);
+ }
+ else
+ {
+ SILABS_LOG("Event received with no handler. Dropping event.");
+ }
+}
diff --git a/examples/platform/silabs/SiWx917/BaseApplication.h b/examples/platform/silabs/SiWx917/BaseApplication.h
new file mode 100644
index 0000000..febd7aa
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/BaseApplication.h
@@ -0,0 +1,186 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+#include "FreeRTOS.h"
+#include "sl_simple_button_instances.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app/clusters/identify-server/identify-server.h>
+#include <ble/BLEEndPoint.h>
+#include <lib/core/CHIPError.h>
+#include <platform/CHIPDeviceLayer.h>
+
+#ifdef DISPLAY_ENABLED
+#include "demo-ui.h"
+#include "lcd.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * BaseApplication Declaration
+ *********************************************************/
+
+class BaseApplication
+{
+
+public:
+ BaseApplication() = default;
+ virtual ~BaseApplication(){};
+
+ /**
+ * @brief Create AppTask task and Event Queue
+ * If an error occurs during creation, application will hang after printing out error code
+ *
+ * @return CHIP_ERROR CHIP_NO_ERROR if no errors
+ */
+ CHIP_ERROR StartAppTask(TaskFunction_t taskFunction);
+
+ /**
+ * @brief PostEvent function that add event to AppTask queue for processing
+ *
+ * @param event AppEvent to post
+ */
+ static void PostEvent(const AppEvent * event);
+
+#ifdef DISPLAY_ENABLED
+ /**
+ * @brief Return LCD object
+ */
+ static SilabsLCD & GetLCD(void);
+#endif
+
+ /**
+ * @brief Event handler when a button is pressed
+ * Function posts an event for button processing
+ *
+ * @param buttonHandle APP_LIGHT_SWITCH or APP_FUNCTION_BUTTON
+ * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+ * SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+ */
+ virtual void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction) = 0;
+
+ /**
+ * @brief Function called to start the LED light timer
+ */
+ static void StartStatusLEDTimer(void);
+
+ /**
+ * @brief Function to stop LED light timer
+ * Turns off Status LED before stopping timer
+ */
+ static void StopStatusLEDTimer(void);
+
+ enum Function_t
+ {
+ kFunction_NoneSelected = 0,
+ kFunction_SoftwareUpdate = 0,
+ kFunction_StartBleAdv = 1,
+ kFunction_FactoryReset = 2,
+
+ kFunction_Invalid
+ } Function;
+
+protected:
+ CHIP_ERROR Init(Identify * identifyObj);
+
+ /**
+ * @brief Function called to start the function timer
+ *
+ * @param aTimeoutMs timer duration in ms
+ */
+ static void StartFunctionTimer(uint32_t aTimeoutMs);
+
+ /**
+ * @brief Function to stop function timer
+ */
+ static void CancelFunctionTimer(void);
+
+ /**
+ * @brief Function call event callback function for processing
+ *
+ * @param event triggered event to be processed
+ */
+ void DispatchEvent(AppEvent * event);
+
+ /**
+ * @brief Function Timer finished callback function
+ * Post an FunctionEventHandler event
+ *
+ * @param xTimer timer that finished
+ */
+ static void FunctionTimerEventHandler(TimerHandle_t xTimer);
+
+ /**
+ * @brief Timer Event processing function
+ * Trigger factory if Press and Hold duration is respected
+ *
+ * @param aEvent post event being processed
+ */
+ static void FunctionEventHandler(AppEvent * aEvent);
+
+ /**
+ * @brief PB0 Button event processing function
+ * Press and hold will trigger a factory reset timer start
+ * Press and release will restart BLEAdvertising if not commisionned
+ *
+ * @param aEvent button event being processed
+ */
+ static void ButtonHandler(AppEvent * aEvent);
+
+ /**
+ * @brief Light Timer finished callback function
+ * Calls LED processing function
+ *
+ * @param xTimer timer that finished
+ */
+ static void LightTimerEventHandler(TimerHandle_t xTimer);
+
+ /**
+ * @brief Updates device LEDs
+ */
+ static void LightEventHandler();
+
+ /**********************************************************
+ * Protected Attributes declaration
+ *********************************************************/
+ bool mSyncClusterToButtonAction;
+};
diff --git a/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.cpp b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.cpp
new file mode 100644
index 0000000..6e097ff
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.cpp
@@ -0,0 +1,335 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EFR32DeviceDataProvider.h"
+#include <crypto/CHIPCryptoPAL.h>
+#include <lib/support/Base64.h>
+#include <platform/silabs/SilabsConfig.h>
+#include <setup_payload/Base38Encode.h>
+#include <setup_payload/SetupPayload.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace EFR32 {
+
+// using namespace chip::Credentials;
+using namespace chip::DeviceLayer::Internal;
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator)
+{
+ CHIP_ERROR err;
+ uint32_t setupDiscriminator32;
+
+ err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_SetupDiscriminator, setupDiscriminator32);
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ setupDiscriminator32 = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR;
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+
+ VerifyOrReturnLogError(setupDiscriminator32 <= kMaxDiscriminatorValue, CHIP_ERROR_INVALID_ARGUMENT);
+ setupDiscriminator = static_cast<uint16_t>(setupDiscriminator32);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount)
+{
+ CHIP_ERROR err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_Spake2pIterationCount, iterationCount);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ iterationCount = CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT;
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT
+ return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf)
+{
+ static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1;
+
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 };
+ size_t saltB64Len = 0;
+
+ err = SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_Spake2pSalt, saltB64, sizeof(saltB64), saltB64Len);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT)
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ saltB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT);
+ ReturnErrorCodeIf(saltB64Len > sizeof(saltB64), CHIP_ERROR_BUFFER_TOO_SMALL);
+ memcpy(saltB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT, saltB64Len);
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT)
+
+ ReturnErrorOnFailure(err);
+
+ uint8_t saltByteArray[kSpake2pSalt_MaxBase64Len] = { 0 };
+ size_t saltLen = chip::Base64Decode32(saltB64, saltB64Len, saltByteArray);
+ ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ memcpy(saltBuf.data(), saltByteArray, saltLen);
+ saltBuf.reduce_size(saltLen);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
+{
+ static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len =
+ BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1;
+
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 };
+ size_t verifierB64Len = 0;
+
+ err = SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_Spake2pVerifier, verifierB64, sizeof(verifierB64),
+ verifierB64Len);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER)
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ verifierB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER);
+ ReturnErrorCodeIf(verifierB64Len > sizeof(verifierB64), CHIP_ERROR_BUFFER_TOO_SMALL);
+ memcpy(verifierB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER, verifierB64Len);
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER)
+
+ ReturnErrorOnFailure(err);
+
+ verifierLen = chip::Base64Decode32(verifierB64, verifierB64Len, reinterpret_cast<uint8_t *>(verifierB64));
+ ReturnErrorCodeIf(verifierLen > verifierBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ memcpy(verifierBuf.data(), verifierB64, verifierLen);
+ verifierBuf.reduce_size(verifierLen);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSetupPayload(MutableCharSpan & payloadBuf)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ uint8_t payloadBitSet[kTotalPayloadDataSizeInBytes] = { 0 };
+ size_t bitSetLen = 0;
+
+ err = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_SetupPayloadBitSet, payloadBitSet, kTotalPayloadDataSizeInBytes,
+ bitSetLen);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ static constexpr uint8_t kTestSetupPayloadBitset[] = { 0x88, 0xFF, 0x2F, 0x00, 0x44, 0x00, 0xE0, 0x4B, 0x84, 0x68, 0x02 };
+ bitSetLen = sizeof(kTestSetupPayloadBitset);
+ ReturnErrorCodeIf(bitSetLen > kTotalPayloadDataSizeInBytes, CHIP_ERROR_BUFFER_TOO_SMALL);
+ memcpy(payloadBitSet, kTestSetupPayloadBitset, bitSetLen);
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER)
+
+ ReturnErrorOnFailure(err);
+
+ size_t prefixLen = strlen(kQRCodePrefix);
+
+ if (payloadBuf.size() < prefixLen + 1)
+ {
+ err = CHIP_ERROR_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ MutableCharSpan subSpan = payloadBuf.SubSpan(prefixLen, payloadBuf.size() - prefixLen);
+ memcpy(payloadBuf.data(), kQRCodePrefix, prefixLen);
+ err = base38Encode(MutableByteSpan(payloadBitSet), subSpan);
+ // Reduce output span size to be the size of written data
+ payloadBuf.reduce_size(subSpan.size() + prefixLen);
+ }
+
+ return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetVendorName(char * buf, size_t bufSize)
+{
+ size_t vendorNameLen = 0; // without counting null-terminator
+ return SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_VendorName, buf, bufSize, vendorNameLen);
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetVendorId(uint16_t & vendorId)
+{
+ ChipError err = CHIP_NO_ERROR;
+ uint32_t vendorId32 = 0;
+
+ err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_VendorId, vendorId32);
+
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID) && CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ vendorId32 = CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID;
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID) && CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+
+ ReturnErrorOnFailure(err);
+ vendorId = static_cast<uint16_t>(vendorId32);
+ return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetProductName(char * buf, size_t bufSize)
+{
+ size_t productNameLen = 0; // without counting null-terminator
+ return SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_ProductName, buf, bufSize, productNameLen);
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetProductId(uint16_t & productId)
+{
+ ChipError err = CHIP_NO_ERROR;
+ uint32_t productId32 = 0;
+
+ err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_ProductId, productId32);
+
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID) && CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ productId32 = CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID;
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID) && CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ ReturnErrorOnFailure(err);
+
+ productId = static_cast<uint16_t>(productId32);
+ return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetHardwareVersionString(char * buf, size_t bufSize)
+{
+ size_t hardwareVersionStringLen = 0; // without counting null-terminator
+ CHIP_ERROR err =
+ SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_HardwareVersionString, buf, bufSize, hardwareVersionStringLen);
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING)
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ memcpy(buf, CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING, sizeof(bufSize));
+ err = CHIP_NO_ERROR;
+ }
+#endif // CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+ return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetHardwareVersion(uint16_t & hardwareVersion)
+{
+ CHIP_ERROR err;
+ uint32_t hardwareVersion32;
+
+ err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_HardwareVersion, hardwareVersion32);
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION)
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ hardwareVersion32 = CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION;
+ err = CHIP_NO_ERROR;
+ }
+#endif // defined(CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION)
+
+ hardwareVersion = static_cast<uint16_t>(hardwareVersion32);
+ return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
+{
+ ChipError err = CHIP_ERROR_WRONG_KEY_TYPE;
+#if CHIP_ENABLE_ROTATING_DEVICE_ID
+ static_assert(ConfigurationManager::kRotatingDeviceIDUniqueIDLength >= ConfigurationManager::kMinRotatingDeviceIDUniqueIDLength,
+ "Length of unique ID for rotating device ID is smaller than minimum.");
+
+ size_t uniqueIdLen = 0;
+ err =
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_UniqueId, uniqueIdSpan.data(), uniqueIdSpan.size(), uniqueIdLen);
+#ifdef CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ constexpr uint8_t uniqueId[] = CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID;
+
+ ReturnErrorCodeIf(sizeof(uniqueId) > uniqueIdSpan.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+ memcpy(uniqueIdSpan.data(), uniqueId, sizeof(uniqueId));
+ uniqueIdLen = sizeof(uniqueId);
+ }
+#endif // CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID
+
+ ReturnErrorOnFailure(err);
+ uniqueIdSpan.reduce_size(uniqueIdLen);
+
+#endif // CHIP_ENABLE_ROTATING_DEVICE_ID
+ return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSerialNumber(char * buf, size_t bufSize)
+{
+ size_t serialNumberLen = 0; // without counting null-terminator
+ return SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_SerialNum, buf, bufSize, serialNumberLen);
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day)
+{
+ CHIP_ERROR err;
+ constexpr uint8_t kDateStringLength = 10; // YYYY-MM-DD
+ char dateStr[kDateStringLength + 1];
+ size_t dateLen;
+ char * parseEnd;
+
+ err = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_ManufacturingDate, reinterpret_cast<uint8_t *>(dateStr),
+ sizeof(dateStr), dateLen);
+ SuccessOrExit(err);
+
+ VerifyOrExit(dateLen == kDateStringLength, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ // Cast does not lose information, because we then check that we only parsed
+ // 4 digits, so our number can't be bigger than 9999.
+ year = static_cast<uint16_t>(strtoul(dateStr, &parseEnd, 10));
+ VerifyOrExit(parseEnd == dateStr + 4, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ // Cast does not lose information, because we then check that we only parsed
+ // 2 digits, so our number can't be bigger than 99.
+ month = static_cast<uint8_t>(strtoul(dateStr + 5, &parseEnd, 10));
+ VerifyOrExit(parseEnd == dateStr + 7, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ // Cast does not lose information, because we then check that we only parsed
+ // 2 digits, so our number can't be bigger than 99.
+ day = static_cast<uint8_t>(strtoul(dateStr + 8, &parseEnd, 10));
+ VerifyOrExit(parseEnd == dateStr + 10, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+exit:
+ if (err != CHIP_NO_ERROR && err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ ChipLogError(DeviceLayer, "Invalid manufacturing date: %s", dateStr);
+ }
+ return err;
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+EFR32DeviceDataProvider & EFR32DeviceDataProvider::GetDeviceDataProvider()
+{
+ static EFR32DeviceDataProvider sDataProvider;
+ return sDataProvider;
+}
+
+} // namespace EFR32
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.h b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.h
new file mode 100644
index 0000000..99d9049
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <platform/CommissionableDataProvider.h>
+#include <platform/internal/GenericDeviceInstanceInfoProvider.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace EFR32 {
+
+/**
+ * @brief This class provides Commissionable data, Device Attestation Credentials,
+ * and Device Instance Info.
+ */
+
+class EFR32DeviceDataProvider : public CommissionableDataProvider,
+ public Internal::GenericDeviceInstanceInfoProvider<Internal::SILABSConfig>
+{
+public:
+ EFR32DeviceDataProvider() :
+ CommissionableDataProvider(), Internal::GenericDeviceInstanceInfoProvider<Internal::SILABSConfig>(
+ ConfigurationManagerImpl::GetDefaultInstance())
+ {}
+
+ static EFR32DeviceDataProvider & GetDeviceDataProvider();
+ CHIP_ERROR GetSetupPayload(MutableCharSpan & payloadBuf);
+
+ // ===== Members functions that implement the CommissionableDataProvider
+ CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
+ CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
+ CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
+ CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
+ CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
+ // Per spec 5.1.7. Passcode cannot be stored on the device
+ CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override { return CHIP_ERROR_NOT_IMPLEMENTED; };
+ CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
+
+ // ===== Members functions that implement the GenericDeviceInstanceInfoProvider
+ CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
+ CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetProductId(uint16_t & productId) override;
+ CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
+ CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
+ CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
+ CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
+};
+
+} // namespace EFR32
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/examples/platform/silabs/SiWx917/FreeRTOSConfig.h b/examples/platform/silabs/SiWx917/FreeRTOSConfig.h
new file mode 100644
index 0000000..50f4c24
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/FreeRTOSConfig.h
@@ -0,0 +1,274 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/***************************************************************************
+ * # License
+ *
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is Third Party Software licensed by Silicon Labs from a third party
+ * and is governed by the sections of the MSLA applicable to Third Party
+ * Software and the additional terms set forth below.
+ *
+ ******************************************************************************/
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <CHIPProjectConfig.h>
+
+#include <stdint.h>
+
+#include "RTE_Components.h"
+#include CMSIS_device_header
+
+#include "em_assert.h"
+#include "em_device.h"
+
+#if defined(SL_COMPONENT_CATALOG_PRESENT)
+#include "sl_component_catalog.h"
+#endif
+
+#if SL_SYSTEM_VIEW
+#include "SEGGER_SYSVIEW_FreeRTOS.h"
+#endif
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+/* Energy saving modes. */
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+#define configUSE_TICKLESS_IDLE 1
+#else
+#define configUSE_TICKLESS_IDLE 0
+#endif // SL_CATALOG_POWER_MANAGER_PRESENT
+
+#define configTICK_RATE_HZ (1000)
+/* Definition used by Keil to replace default system clock source. */
+#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1
+
+/* Hook function related definitions. */
+#define configUSE_TICK_HOOK (1)
+#define configCHECK_FOR_STACK_OVERFLOW (2)
+#define configUSE_MALLOC_FAILED_HOOK (1)
+#define configUSE_IDLE_HOOK (1)
+
+/* Main functions*/
+/* Run time stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS (0)
+
+/* Co-routine related definitions. */
+#define configUSE_CO_ROUTINES (0)
+#define configMAX_CO_ROUTINE_PRIORITIES (1)
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS (1)
+#define configTIMER_TASK_PRIORITY (40) /* Highest priority */
+#define configTIMER_QUEUE_LENGTH (10)
+#define configTIMER_TASK_STACK_DEPTH (1024)
+
+/* Interrupt priorities used by the kernel port layer itself. These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY (255)
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY 48
+#define configENABLE_FPU 0
+#define configENABLE_MPU 0
+/* FreeRTOS Secure Side Only and TrustZone Security Extension */
+#define configRUN_FREERTOS_SECURE_ONLY 1
+#define configENABLE_TRUSTZONE 0
+/* FreeRTOS MPU specific definitions. */
+#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS (0)
+
+#define configCPU_CLOCK_HZ (SystemCoreClock)
+#define configUSE_PREEMPTION (1)
+#define configUSE_TIME_SLICING (1)
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION (0)
+#define configUSE_TICKLESS_IDLE_SIMPLE_DEBUG (1) /* See into vPortSuppressTicksAndSleep source code for explanation */
+#define configMAX_PRIORITIES (56)
+#define configMINIMAL_STACK_SIZE (320) /* Number of words to use for Idle and Timer stacks */
+
+#ifdef HEAP_MONITORING
+#define configMAX_TASK_NAME_LEN (24)
+#else
+#define configMAX_TASK_NAME_LEN (10)
+#endif // HEAP_MONITORING
+
+#define configUSE_16_BIT_TICKS (0)
+#define configIDLE_SHOULD_YIELD (1)
+#define configUSE_MUTEXES (1)
+#define configUSE_RECURSIVE_MUTEXES (1)
+#define configUSE_COUNTING_SEMAPHORES (1)
+#define configUSE_TASK_NOTIFICATIONS 1
+#define configUSE_TRACE_FACILITY 1
+#define configQUEUE_REGISTRY_SIZE (10)
+#define configUSE_QUEUE_SETS (0)
+#define configUSE_NEWLIB_REENTRANT (1)
+#define configENABLE_BACKWARD_COMPATIBILITY (1)
+#define configSUPPORT_STATIC_ALLOCATION (1)
+#define configSUPPORT_DYNAMIC_ALLOCATION (1)
+
+#ifndef configTOTAL_HEAP_SIZE
+#ifdef SL_WIFI
+#define configTOTAL_HEAP_SIZE ((size_t)(34 * 1024))
+#else
+#define configTOTAL_HEAP_SIZE ((size_t)(20 * 1024))
+#endif
+#endif // configTOTAL_HEAP_SIZE
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet (1)
+#define INCLUDE_uxTaskPriorityGet (1)
+#define INCLUDE_vTaskDelete (1)
+#define INCLUDE_vTaskSuspend (1)
+#define INCLUDE_xResumeFromISR (1)
+#define INCLUDE_vTaskDelayUntil (1)
+#define INCLUDE_vTaskDelay (1)
+#define INCLUDE_xTaskGetSchedulerState (1)
+#define INCLUDE_xTaskGetCurrentTaskHandle (1)
+#define INCLUDE_uxTaskGetStackHighWaterMark (1)
+#define INCLUDE_xTaskGetIdleTaskHandle (1)
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle (1)
+#define INCLUDE_pcTaskGetTaskName (1)
+#define INCLUDE_eTaskGetState (1)
+#define INCLUDE_xEventGroupSetBitFromISR (1)
+#define INCLUDE_xEventGroupSetBitsFromISR (1)
+#define INCLUDE_xSemaphoreGetMutexHolder (1)
+#define INCLUDE_xTimerPendFunctionCall (1)
+#define INCLUDE_xTaskGetHandle (1)
+
+/* Stop if an assertion fails. */
+#define configASSERT(x) \
+ if ((x) == 0) \
+ { \
+ taskDISABLE_INTERRUPTS(); \
+ printf("\nFREERTOS ASSERT ( %s )\n", #x); \
+ for (;;) \
+ ; \
+ }
+#define configASSERTNULL(x) \
+ if ((x) == NULL) \
+ { \
+ taskDISABLE_INTERRUPTS(); \
+ for (;;) \
+ ; \
+ }
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names. */
+#define vPortSVCHandler SVC_Handler
+#define xPortPendSVHandler PendSV_Handler
+/* Ensure Cortex-M port compatibility. */
+#define SysTick_Handler xPortSysTickHandler
+
+/* Thread local storage pointers used by the SDK */
+#ifndef configNUM_SDK_THREAD_LOCAL_STORAGE_POINTERS
+#define configNUM_SDK_THREAD_LOCAL_STORAGE_POINTERS 0
+#endif
+
+#if defined(__GNUC__)
+/* For the linker. */
+#define fabs __builtin_fabs
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/LEDWidget.cpp b/examples/platform/silabs/SiWx917/LEDWidget.cpp
new file mode 100644
index 0000000..10ffcac
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/LEDWidget.cpp
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LEDWidget.h"
+
+extern "C" {
+#include "sl_simple_led_instances.h"
+}
+
+#include <platform/CHIPDeviceLayer.h>
+
+using namespace ::chip::System;
+
+void LEDWidget::InitGpio(void)
+{
+ // Sets gpio pin mode for ALL board Leds.
+ sl_simple_led_init_instances();
+}
+
+void LEDWidget::Init(const sl_led_t * led)
+{
+ mLastChangeTimeMS = 0;
+ mBlinkOnTimeMS = 0;
+ mBlinkOffTimeMS = 0;
+ mLed = led;
+
+ Set(false);
+}
+
+void LEDWidget::Invert(void)
+{
+ if (mLed)
+ {
+ sl_led_toggle(mLed);
+ }
+}
+
+void LEDWidget::Set(bool state)
+{
+ mLastChangeTimeMS = mBlinkOnTimeMS = mBlinkOffTimeMS = 0;
+ if (mLed)
+ {
+ state ? sl_led_turn_on(mLed) : sl_led_turn_off(mLed);
+ }
+}
+
+void LEDWidget::Blink(uint32_t changeRateMS)
+{
+ Blink(changeRateMS, changeRateMS);
+}
+
+void LEDWidget::Blink(uint32_t onTimeMS, uint32_t offTimeMS)
+{
+ mBlinkOnTimeMS = onTimeMS;
+ mBlinkOffTimeMS = offTimeMS;
+ Animate();
+}
+
+void LEDWidget::Animate()
+{
+ if (mBlinkOnTimeMS != 0 && mBlinkOffTimeMS != 0)
+ {
+ uint64_t nowMS = chip::System::SystemClock().GetMonotonicMilliseconds64().count();
+ uint64_t stateDurMS = sl_led_get_state(mLed) ? mBlinkOnTimeMS : mBlinkOffTimeMS;
+ uint64_t nextChangeTimeMS = mLastChangeTimeMS + stateDurMS;
+
+ if (nextChangeTimeMS < nowMS)
+ {
+ Invert();
+ mLastChangeTimeMS = nowMS;
+ }
+ }
+}
diff --git a/examples/platform/silabs/SiWx917/LEDWidget.h b/examples/platform/silabs/SiWx917/LEDWidget.h
new file mode 100644
index 0000000..d779cb9
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/LEDWidget.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "sl_led.h"
+#include <stdint.h>
+
+class LEDWidget
+{
+public:
+ static void InitGpio(void);
+ void Init(const sl_led_t * led);
+ void Set(bool state);
+ void Invert(void);
+ void Blink(uint32_t changeRateMS);
+ void Blink(uint32_t onTimeMS, uint32_t offTimeMS);
+ void Animate();
+
+private:
+ uint64_t mLastChangeTimeMS;
+ uint32_t mBlinkOnTimeMS;
+ uint32_t mBlinkOffTimeMS;
+ const sl_led_t * mLed;
+};
diff --git a/examples/platform/silabs/SiWx917/MemMonitoring.cpp b/examples/platform/silabs/SiWx917/MemMonitoring.cpp
new file mode 100644
index 0000000..9da075e
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/MemMonitoring.cpp
@@ -0,0 +1,111 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MemMonitoring.h"
+
+#include "AppConfig.h"
+#include "FreeRTOS.h"
+#include <platform/CHIPDeviceLayer.h>
+
+#define BLE_STACK_TASK_NAME "Bluetooth stack"
+#define BLE_LINK_TASK_NAME "Bluetooth linklayer"
+
+static StackType_t monitoringStack[MONITORING_STACK_SIZE_byte / sizeof(StackType_t)];
+static StaticTask_t monitoringTaskStruct;
+
+size_t nbAllocSuccess = 0;
+size_t nbFreeSuccess = 0;
+size_t largestBlockAllocated = 0;
+
+void MemMonitoring::startHeapMonitoring()
+{
+ xTaskCreateStatic(HeapMonitoring, "Monitoring", MONITORING_STACK_SIZE_byte / sizeof(StackType_t), NULL, 1, monitoringStack,
+ &monitoringTaskStruct);
+}
+
+void MemMonitoring::HeapMonitoring(void * pvParameter)
+{
+
+ UBaseType_t appTaskValue;
+ UBaseType_t bleEventTaskValue;
+ UBaseType_t bleTaskValue;
+ UBaseType_t linkLayerTaskValue;
+ UBaseType_t openThreadTaskValue;
+ UBaseType_t eventLoopTaskValue;
+
+ TaskHandle_t eventLoopHandleStruct = xTaskGetHandle(CHIP_DEVICE_CONFIG_CHIP_TASK_NAME);
+ TaskHandle_t otTaskHandle = xTaskGetHandle(CHIP_DEVICE_CONFIG_THREAD_TASK_NAME);
+ TaskHandle_t appTaskHandle = xTaskGetHandle(APP_TASK_NAME);
+ TaskHandle_t bleStackTaskHandle = xTaskGetHandle(BLE_STACK_TASK_NAME);
+ TaskHandle_t bleLinkTaskHandle = xTaskGetHandle(BLE_LINK_TASK_NAME);
+ TaskHandle_t bleEventTaskHandle = xTaskGetHandle(CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME);
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+ UBaseType_t lwipTaskValue;
+ TaskHandle_t lwipHandle = xTaskGetHandle(TCPIP_THREAD_NAME);
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+ while (true)
+ {
+ appTaskValue = uxTaskGetStackHighWaterMark(appTaskHandle);
+ bleEventTaskValue = uxTaskGetStackHighWaterMark(bleEventTaskHandle);
+ bleTaskValue = uxTaskGetStackHighWaterMark(bleStackTaskHandle);
+ linkLayerTaskValue = uxTaskGetStackHighWaterMark(bleLinkTaskHandle);
+ openThreadTaskValue = uxTaskGetStackHighWaterMark(otTaskHandle);
+ eventLoopTaskValue = uxTaskGetStackHighWaterMark(eventLoopHandleStruct);
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+ lwipTaskValue = uxTaskGetStackHighWaterMark(lwipHandle);
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+ SILABS_LOG("=============================");
+ SILABS_LOG(" ");
+ SILABS_LOG("Largest Block allocated 0x%x", largestBlockAllocated);
+ SILABS_LOG("Number Of Successful Alloc 0x%x", nbAllocSuccess);
+ SILABS_LOG("Number Of Successful Frees 0x%x", nbFreeSuccess);
+ SILABS_LOG(" ");
+ SILABS_LOG("App Task most bytes ever Free 0x%x", (appTaskValue * 4));
+ SILABS_LOG("BLE Event most bytes ever Free 0x%x", (bleEventTaskValue * 4));
+ SILABS_LOG("BLE Stack most bytes ever Free 0x%x", (bleTaskValue * 4));
+ SILABS_LOG("Link Layer Task most bytes ever Free 0x%x", (linkLayerTaskValue * 4));
+ SILABS_LOG("OpenThread Task most bytes ever Free 0x%x", (openThreadTaskValue * 4));
+ SILABS_LOG("Event Loop Task most bytes ever Free 0x%x", (eventLoopTaskValue * 4));
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+ SILABS_LOG("LWIP Task most bytes ever Free 0x%x", (lwipTaskValue * 4));
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+ SILABS_LOG(" ");
+ SILABS_LOG("=============================");
+ vTaskDelay(pdMS_TO_TICKS(5000));
+ }
+}
+
+extern "C" void memMonitoringTrackAlloc(void * ptr, size_t size)
+{
+ if (ptr != NULL)
+ {
+ nbAllocSuccess++;
+ if (largestBlockAllocated < size)
+ {
+ largestBlockAllocated = size;
+ }
+ }
+}
+
+extern "C" void memMonitoringTrackFree(void * ptr, size_t size)
+{
+ nbFreeSuccess++;
+}
diff --git a/examples/platform/silabs/SiWx917/OTAConfig.cpp b/examples/platform/silabs/SiWx917/OTAConfig.cpp
new file mode 100644
index 0000000..1056cf5
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/OTAConfig.cpp
@@ -0,0 +1,101 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OTAConfig.h"
+
+#include "application_properties.h"
+#include <app/server/Server.h>
+
+#if defined(SL_COMPONENT_CATALOG_PRESENT)
+#include "sl_component_catalog.h"
+#endif
+
+// Only include app properties if the Gecko SDK component that does it automatically isn't present
+#if !defined(SL_CATALOG_GECKO_BOOTLOADER_INTERFACE_PRESENT)
+// Header used for building the image GBL file
+#define APP_PROPERTIES_VERSION 1
+#define APP_PROPERTIES_ID \
+ { \
+ 0 \
+ }
+
+__attribute__((used)) ApplicationProperties_t sl_app_properties = {
+ /// @brief Magic value indicating that this is an ApplicationProperties_t
+ /// Must equal @ref APPLICATION_PROPERTIES_MAGIC
+ .magic = APPLICATION_PROPERTIES_MAGIC,
+
+ /// Version number of this struct
+ .structVersion = APPLICATION_PROPERTIES_VERSION,
+
+ /// Type of signature this application is signed with
+ .signatureType = APPLICATION_SIGNATURE_NONE,
+
+ /// Location of the signature. Typically a pointer to the end of application
+ .signatureLocation = 0,
+
+ /// Information about the application
+ .app = {
+
+ /// Bitfield representing type of application
+ /// e.g. @ref APPLICATION_TYPE_BLUETOOTH_APP
+ .type = APPLICATION_TYPE_THREAD,
+
+ /// Version number for this application
+ .version = APP_PROPERTIES_VERSION,
+
+ /// Capabilities of this application
+ .capabilities = 0,
+
+ /// Unique ID (e.g. UUID/GUID) for the product this application is built for
+ .productId = APP_PROPERTIES_ID,
+ },
+
+ /// Pointer to information about the certificate
+ .cert = NULL,
+
+ /// Pointer to Long Token Data Section
+ .longTokenSectionAddress = NULL,
+};
+#endif // SL_CATALOG_GECKO_BOOTLOADER_INTERFACE_PRESENT
+
+// Global OTA objects
+chip::DefaultOTARequestor gRequestorCore;
+chip::DefaultOTARequestorStorage gRequestorStorage;
+chip::DeviceLayer::DefaultOTARequestorDriver gRequestorUser;
+chip::BDXDownloader gDownloader;
+chip::OTAImageProcessorImpl gImageProcessor;
+
+void OTAConfig::Init()
+{
+ // Initialize and interconnect the Requestor and Image Processor objects -- START
+ SetRequestorInstance(&gRequestorCore);
+
+ gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage());
+ gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader);
+
+ // Periodic query timeout must be set prior to requestor being initialized
+ gRequestorUser.SetPeriodicQueryTimeout(OTA_PERIODIC_TIMEOUT);
+ gRequestorUser.Init(&gRequestorCore, &gImageProcessor);
+
+ gImageProcessor.SetOTAImageFile("test.txt");
+ gImageProcessor.SetOTADownloader(&gDownloader);
+
+ // Connect the Downloader and Image Processor objects
+ gDownloader.SetImageProcessorDelegate(&gImageProcessor);
+ // Initialize and interconnect the Requestor and Image Processor objects -- END
+}
diff --git a/examples/platform/silabs/SiWx917/OTAConfig.h b/examples/platform/silabs/SiWx917/OTAConfig.h
new file mode 100644
index 0000000..a4f8ac4
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/OTAConfig.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <app/clusters/ota-requestor/BDXDownloader.h>
+#include <app/clusters/ota-requestor/DefaultOTARequestor.h>
+#include <app/clusters/ota-requestor/DefaultOTARequestorDriver.h>
+#include <app/clusters/ota-requestor/DefaultOTARequestorStorage.h>
+#include <platform/silabs/EFR32/OTAImageProcessorImpl.h>
+
+class OTAConfig
+{
+public:
+ OTAConfig(){};
+
+ static void Init();
+ static constexpr uint32_t kInitOTARequestorDelaySec = 3;
+};
diff --git a/examples/platform/silabs/SiWx917/TemperatureSensor.cpp b/examples/platform/silabs/SiWx917/TemperatureSensor.cpp
new file mode 100644
index 0000000..69ba106
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/TemperatureSensor.cpp
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TemperatureSensor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// This is a C implementation. Need the ifdef __cplusplus else we get linking issues
+#include "sl_sensor_rht.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+namespace TemperatureSensor {
+constexpr uint16_t kSensorTemperatureOffset = 800;
+
+sl_status_t Init()
+{
+ return sl_sensor_rht_init();
+}
+
+sl_status_t GetTemp(uint32_t * relativeHumidity, int16_t * temperature)
+{
+ // Sensor resolution 0.001 C
+ // DataModel resolution 0.01 C
+ int32_t temp;
+ sl_status_t status = sl_sensor_rht_get(relativeHumidity, &temp);
+ *temperature = static_cast<int16_t>(temp / 10) - kSensorTemperatureOffset;
+ return status;
+}
+}; // namespace TemperatureSensor
diff --git a/examples/platform/silabs/SiWx917/TemperatureSensor.h b/examples/platform/silabs/SiWx917/TemperatureSensor.h
new file mode 100644
index 0000000..116287e
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/TemperatureSensor.h
@@ -0,0 +1,28 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "sl_status.h"
+#include <stdint.h>
+
+namespace TemperatureSensor {
+sl_status_t Init();
+sl_status_t GetTemp(uint32_t * relativeHumidity, int16_t * temperature);
+}; // namespace TemperatureSensor
diff --git a/examples/platform/silabs/SiWx917/args.gni b/examples/platform/silabs/SiWx917/args.gni
new file mode 100644
index 0000000..1726b62
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/args.gni
@@ -0,0 +1,21 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+
+chip_ble_project_config_include = "<CHIPProjectConfig.h>"
+chip_device_project_config_include = "<CHIPProjectConfig.h>"
+chip_project_config_include = "<CHIPProjectConfig.h>"
+chip_inet_project_config_include = "<CHIPProjectConfig.h>"
+chip_system_project_config_include = "<CHIPProjectConfig.h>"
diff --git a/examples/platform/silabs/SiWx917/board_config.h b/examples/platform/silabs/SiWx917/board_config.h
new file mode 100644
index 0000000..8c495b4
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/board_config.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes dev borad compile-time configuration constants for efr32.
+ *
+ */
+
+#pragma once
+
+/// Dev board suppports OQPSK modulation in 2.4GHz band.
+#define RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT 1
+#define RADIO_CONFIG_915MHZ_OQPSK_SUPPORT 0
+
+/// The PA(s) is(are) fed from the DCDC
+#if (BRD4166A)
+#define RADIO_CONFIG_PA_USES_DCDC 1
+#else
+#define RADIO_CONFIG_PA_USES_DCDC 0
+#endif
+
+#ifndef RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+#define RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT 0 /// Set to 1 to enable debug counters in radio.c
+#endif
+
+#ifndef RADIO_CONFIG_DMP_SUPPORT
+#define RADIO_CONFIG_DMP_SUPPORT 0 /// Set to 1 to enable Dynamic Multi-Protocol support in radio.c
+#endif
diff --git a/examples/platform/silabs/SiWx917/display/demo-ui-bitmaps.h b/examples/platform/silabs/SiWx917/display/demo-ui-bitmaps.h
new file mode 100644
index 0000000..4eca9c0
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui-bitmaps.h
@@ -0,0 +1,356 @@
+/***************************************************************************/ /**
+ * @file
+ * @brief User Interface bitmaps for demo.
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com</b>
+ *******************************************************************************
+ *
+ * The licensor of this software is Silicon
+ *Laboratories Inc. Your use of this software is
+ *governed by the terms of Silicon Labs Master
+ *Software License Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement.
+ *This software is distributed to you in Source Code
+ *format and is governed by the sections of the MSLA
+ *applicable to Source Code.
+ *
+ ******************************************************************************/
+
+#ifndef SILABS_DEMO_UI_BITMAPS_H
+#define SILABS_DEMO_UI_BITMAPS_H
+
+#define SILICONLABS_BITMAP_WIDTH 128
+#define SILICONLABS_BITMAP_HEIGHT 45
+
+#define ZIGBEE_BITMAP_WIDTH 16
+#define ZIGBEE_BITMAP_HEIGHT 16
+
+#define RAIL_BITMAP_WIDTH 16
+#define RAIL_BITMAP_HEIGHT 16
+
+#define CONNECT_BITMAP_WIDTH 16
+#define CONNECT_BITMAP_HEIGHT 16
+
+#define BLUETOOTH_BITMAP_WIDTH 16
+#define BLUETOOTH_BITMAP_HEIGHT 18
+
+#define SILABS_BITMAP \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xfd, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x3f, 0x00, \
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xfe, \
+ 0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xf0, 0xff, \
+ 0xff, 0xff, 0x1f, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xe0, 0xff, 0xff, 0xff, 0xc3, 0xff, \
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0xc0, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, \
+ 0xff, 0x01, 0xc0, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x80, 0xff, \
+ 0xff, 0x01, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x80, 0xff, 0x7f, 0x00, 0xff, 0xff, \
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, \
+ 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x80, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x01, \
+ 0x00, 0x00, 0xc0, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xe0, 0xff, \
+ 0x01, 0xc0, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xc0, 0xff, 0xff, \
+ 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf0, 0x7f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, \
+ 0x0f, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0x0f, \
+ 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xff, 0x07, 0x00, 0x00, 0xf0, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x1f, 0x80, 0xff, 0x07, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0x3f, 0xf8, 0xff, 0xff, 0x1f, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff, \
+ 0x0f, 0xf0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0x03, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x07, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x3f, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x83, 0xff, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0xfc, 0xff, 0xff, 0xe1, 0xff, 0xff, 0x03, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, \
+ 0xf8, 0xff, 0xff, 0x03, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x03, \
+ 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x01, \
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, \
+ 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0xff, \
+ 0x1f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+
+#define THREAD_BITMAP_WIDTH 16
+#define THREAD_BITMAP_HEIGHT 18
+
+#define THREAD_BITMAP \
+ 0x1F, 0xF8, 0x07, 0xE0, 0x03, 0xCE, 0x01, 0x9F, 0x01, 0xB3, 0x00, 0x33, 0xF0, 0x3F, 0xF8, 0x1F, 0x0C, 0x03, 0x0C, 0x03, 0x18, \
+ 0x03, 0x11, 0x83, 0x01, 0x83, 0x03, 0xC3, 0x07, 0xE3, 0x1F, 0xFB, 0x7f, 0xff, 0xff, 0xff
+
+#define WIFI_BITMAP_WIDTH 18
+#define WIFI_BITMAP_HEIGHT 18
+
+#define WIFI_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x01, 0xE0, 0x03, 0x00, 0xC7, 0xFF, 0xB8, 0xFF, 0xF7, 0x07, 0xF8, 0x0F, 0xC0, 0x3F, \
+ 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x7F, 0xF8, 0xFF, 0xE1, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F
+
+#define MATTER_LOGO_WIDTH 18
+#define MATTER_LOGO_HEIGHT 17
+
+#define MATTER_LOGO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xCF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0x12, 0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0xF3, 0x3F, 0x8F, \
+ 0x7F, 0xFC, 0xFC, 0xFC, 0xE3, 0xF1, 0x87, 0x87, 0xC7, 0xDE, 0x88, 0x33, 0xC7, 0xCF, 0xFC, 0xFF, 0xFF, 0x03
+
+// APP Logo, boolean only. must be 64x64
+#if IS_DEMO_SWITCH
+#define ON_DEMO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \
+ 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0xC0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, \
+ 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define OFF_DEMO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \
+ 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, \
+ 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, \
+ 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, \
+ 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, \
+ 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, \
+ 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \
+ 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+#elif IS_DEMO_LIGHT
+#define ON_DEMO_BITMAP \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, \
+ 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x1f, 0xfe, 0x07, 0xe0, \
+ 0x7f, 0xf8, 0xff, 0xff, 0x3f, 0xfc, 0x00, 0x00, 0x3f, 0xfc, 0xff, 0xff, 0x7f, 0x3c, 0xe0, 0x07, 0x3c, 0xfe, 0xff, 0xff, \
+ 0xff, 0x1f, 0xfe, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, \
+ 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0x0f, 0x38, 0xfe, 0xff, 0xff, 0x7f, 0x1c, 0xf0, 0x0f, 0x38, 0xfe, 0x03, 0xc0, 0x7f, 0x1c, 0xf0, 0x0f, \
+ 0x38, 0xfe, 0x27, 0xe9, 0x7f, 0x1c, 0xf0, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xe7, 0xe7, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0xfe, 0xef, 0xf7, 0x7f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xef, 0xf7, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xef, 0xf3, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xcf, 0xf3, \
+ 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xdf, 0xfb, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xdf, 0xfb, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xe3, 0x9f, 0xf9, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x9f, 0xf9, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x9f, 0xfd, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xbf, 0xfd, 0xf1, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0xfc, 0xf8, 0xff, 0xff, 0xff, \
+ 0xff, 0x3f, 0x3e, 0x7c, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, \
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+
+#define OFF_DEMO_BITMAP \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x07, 0xfc, 0xff, 0xff, 0xff, \
+ 0xff, 0x1f, 0xfe, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, \
+ 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, \
+ 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, \
+ 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, \
+ 0xff, 0x3f, 0xfe, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, \
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+#elif IS_DEMO_LOCK
+#define ON_DEMO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, \
+ 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xE0, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x0F, 0xFC, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F, \
+ 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, \
+ 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define OFF_DEMO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, \
+ 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xE0, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x0F, 0xFC, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F, \
+ 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, \
+ 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, \
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+#elif IS_DEMO_THERMOSTAT
+#define ON_DEMO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x81, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, \
+ 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, \
+ 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, \
+ 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, \
+ 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+#define OFF_DEMO_BITMAP ON_DEMO_BITMAP
+
+#else // Unknown demo....
+#define ON_DEMO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, \
+ 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0x0F, \
+ 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, \
+ 0x0F, 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 0xE0, 0x07, 0xFE, 0xFF, 0xFF, 0x7F, 0xC0, 0x03, 0xC0, 0x03, 0xFE, 0xFF, 0xFF, \
+ 0x7F, 0xC0, 0x03, 0xC0, 0x03, 0xFE, 0xFF, 0xFF, 0x3F, 0xC0, 0x03, 0xC0, 0x03, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, \
+ 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, \
+ 0x8F, 0x01, 0x80, 0x01, 0x80, 0xF1, 0xFF, 0xFF, 0xCF, 0x03, 0xC0, 0x03, 0xC0, 0xF3, 0xFF, 0xFF, 0xEF, 0x07, 0xE0, 0x07, \
+ 0xE0, 0xF7, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x3F, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x7E, 0x7E, 0x7E, 0x7E, 0xFE, 0xFF, 0xFF, 0x3F, 0xFC, 0x3F, 0xFC, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0x1F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0xE0, 0x07, 0xE0, 0x07, 0xF8, 0xFF, 0xFF, 0x3F, 0xC0, 0x03, 0xC0, 0x03, 0xFC, 0xFF, 0xFF, 0x3F, 0x80, 0x01, 0x80, \
+ 0x01, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, \
+ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define OFF_DEMO_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, \
+ 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, \
+ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, \
+ 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, \
+ 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, \
+ 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, \
+ 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, \
+ 0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, \
+ 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, \
+ 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, \
+ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#endif
+
+#endif // SILABS_DEMO_UI_BITMAPS_H
diff --git a/examples/platform/silabs/SiWx917/display/demo-ui.c b/examples/platform/silabs/SiWx917/display/demo-ui.c
new file mode 100644
index 0000000..73a8d52
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui.c
@@ -0,0 +1,136 @@
+/**
+ * @file
+ * @brief User Interface core logic for demo.
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com</b>
+ *******************************************************************************
+ *
+ * The licensor of this software is Silicon
+ *Laboratories Inc. Your use of this software is
+ *governed by the terms of Silicon Labs Master
+ *Software License Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement.
+ *This software is distributed to you in Source Code
+ *format and is governed by the sections of the MSLA
+ *applicable to Source Code.
+ *
+ ******************************************************************************/
+
+#include "demo-ui.h"
+#include "demo-ui-bitmaps.h"
+#include "dmd/dmd.h"
+#include "em_types.h"
+#include "glib.h"
+#include <stdio.h>
+#include <string.h>
+
+// Main Logo and App image
+#define SILICONLABS_X_POSITION ((glibContext.pDisplayGeometry->xSize - SILICONLABS_BITMAP_WIDTH) / 2)
+#define SILICONLABS_Y_POSITION 0
+#define APP_BITMAP_WIDTH 64
+#define APP_BITMAP_HEIGHT 64
+#define APP_X_POSITION ((glibContext.pDisplayGeometry->xSize - APP_BITMAP_WIDTH) / 2)
+#define APP_Y_POSITION (glibContext.pDisplayGeometry->ySize - APP_BITMAP_HEIGHT - 5)
+#define PROT1_ID_X_POSITION 1
+#define PROT2_ID_X_POSITION 79
+
+// Matter Logo
+#define PROT2_BITMAP_WIDTH MATTER_LOGO_WIDTH
+#define PROT2_BITMAP_HEIGHT MATTER_LOGO_HEIGHT
+#define PROT2_X_POSITION 104
+#define PROT2_Y_POSITION (APP_Y_POSITION + (APP_Y_POSITION / 2))
+#define PROT2_BITMAP (matterLogoBitmap)
+#define PROT2_BITMAP_CONN (matterLogoBitmap)
+
+// Networking Protocol Logo
+#ifdef SL_WIFI
+#define PROT1_BITMAP_WIDTH WIFI_BITMAP_WIDTH
+#define PROT1_BITMAP_HEIGHT WIFI_BITMAP_HEIGHT
+#define PROT1_X_POSITION 8
+#define PROT1_Y_POSITION (APP_Y_POSITION + (APP_Y_POSITION / 2))
+#define PROT1_BITMAP (networkBitMap)
+#define PROT1_BITMAP_CONN (networkBitMap)
+#else
+#define PROT1_BITMAP_WIDTH THREAD_BITMAP_WIDTH
+#define PROT1_BITMAP_HEIGHT THREAD_BITMAP_HEIGHT
+#define PROT1_X_POSITION 8
+#define PROT1_Y_POSITION (APP_Y_POSITION + (APP_Y_POSITION / 2))
+#define PROT1_BITMAP (networkBitMap)
+#define PROT1_BITMAP_CONN (networkBitMap)
+#endif
+
+/*******************************************************************************
+ *************************** LOCAL VARIABLES ********************************
+ ******************************************************************************/
+static GLIB_Context_t glibContext; /* Global glib context */
+
+static const uint8_t siliconlabsBitmap[] = { SILABS_BITMAP };
+static const uint8_t matterLogoBitmap[] = { MATTER_LOGO_BITMAP };
+
+static const uint8_t OnStateBitMap[] = { ON_DEMO_BITMAP };
+static const uint8_t OffStateBitMap[] = { OFF_DEMO_BITMAP };
+
+#ifdef SL_WIFI
+static const uint8_t networkBitMap[] = { WIFI_BITMAP };
+#else
+static const uint8_t networkBitMap[] = { THREAD_BITMAP };
+#endif
+
+// Future usage
+// static const uint8_t unconnectedBitMap[] = { QUESTION_MARK_BITMAP };
+
+/*******************************************************************************
+ ************************** LOCAL FUNCTIONS ********************************
+ ******************************************************************************/
+static void demoUIDisplayLogo(void)
+{
+ GLIB_drawBitmap(&glibContext, SILICONLABS_X_POSITION, SILICONLABS_Y_POSITION, SILICONLABS_BITMAP_WIDTH,
+ SILICONLABS_BITMAP_HEIGHT, siliconlabsBitmap);
+}
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+void demoUIInit(GLIB_Context_t * context)
+{
+ memcpy(&glibContext, context, sizeof(GLIB_Context_t));
+}
+
+void demoUIDisplayHeader(char * name)
+{
+ demoUIDisplayLogo();
+ if (APP_NAME_MAX_LENGTH >= strlen(name))
+ {
+ GLIB_drawStringOnLine(&glibContext, name, 5, GLIB_ALIGN_CENTER, 0, 0, true);
+ }
+ DMD_updateDisplay();
+}
+
+void demoUIDisplayApp(bool on)
+{
+ GLIB_drawBitmap(&glibContext, APP_X_POSITION, APP_Y_POSITION, APP_BITMAP_WIDTH, APP_BITMAP_HEIGHT,
+ (on ? OnStateBitMap : OffStateBitMap));
+ DMD_updateDisplay();
+}
+
+void demoUIDisplayProtocol(demoUIProtocol protocol, bool isConnected)
+{
+ GLIB_drawBitmap(&glibContext, (protocol == DEMO_UI_PROTOCOL1 ? PROT1_X_POSITION : PROT2_X_POSITION),
+ (protocol == DEMO_UI_PROTOCOL1 ? PROT1_Y_POSITION : PROT2_Y_POSITION),
+ (protocol == DEMO_UI_PROTOCOL1 ? PROT1_BITMAP_WIDTH : PROT2_BITMAP_WIDTH),
+ (protocol == DEMO_UI_PROTOCOL1 ? PROT1_BITMAP_HEIGHT : PROT2_BITMAP_HEIGHT),
+ (protocol == DEMO_UI_PROTOCOL1 ? (isConnected ? PROT1_BITMAP_CONN : PROT1_BITMAP)
+ : (isConnected ? PROT2_BITMAP_CONN : PROT2_BITMAP)));
+ DMD_updateDisplay();
+}
+
+void demoUIClearMainScreen(uint8_t * name)
+{
+ GLIB_clear(&glibContext);
+ demoUIDisplayHeader((char *) name);
+ demoUIDisplayApp(false);
+ demoUIDisplayProtocol(DEMO_UI_PROTOCOL1, false);
+ demoUIDisplayProtocol(DEMO_UI_PROTOCOL2, false);
+}
diff --git a/examples/platform/silabs/SiWx917/display/demo-ui.h b/examples/platform/silabs/SiWx917/display/demo-ui.h
new file mode 100644
index 0000000..6197a4e
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui.h
@@ -0,0 +1,139 @@
+/***************************************************************************/ /**
+ * @file
+ * @brief User Interface for demo.
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com</b>
+ *******************************************************************************
+ *
+ * The licensor of this software is Silicon
+ *Laboratories Inc. Your use of this software is
+ *governed by the terms of Silicon Labs Master
+ *Software License Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement.
+ *This software is distributed to you in Source Code
+ *format and is governed by the sections of the MSLA
+ *applicable to Source Code.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "glib.h"
+/**************************************************************************/ /**
+ * DEMO UI uses the underlying DMD interface and the
+ *GLIB and exposes several wrapper functions to
+ *application. These functions are used to display
+ * different bitmaps for the demo.
+ *
+ ******************************************************************************/
+
+#define APP_NAME_MAX_LENGTH 20
+
+/*******************************************************************************
+ ******************************** ENUMS ************************************
+ ******************************************************************************/
+
+typedef enum
+{
+ DEMO_UI_PROTOCOL1,
+ DEMO_UI_PROTOCOL2
+} demoUIProtocol;
+
+typedef enum
+{
+ DEMO_UI_LIGHT_OFF,
+ DEMO_UI_LIGHT_ON
+} demoUILightState_t;
+
+typedef enum
+{
+ DEMO_UI_DIRECTION_PROT1,
+ DEMO_UI_DIRECTION_PROT2,
+ DEMO_UI_DIRECTION_SWITCH,
+ DEMO_UI_DIRECTION_INVALID
+} demoUILightDirection_t;
+
+typedef enum
+{
+ DEMO_UI_NO_NETWORK,
+ DEMO_UI_SCANNING,
+ DEMO_UI_JOINING,
+ DEMO_UI_FORMING,
+ DEMO_UI_NETWORK_UP,
+ DEMO_UI_STATE_UNKNOWN
+} demoUIZigBeeNetworkState_t;
+
+/*******************************************************************************
+ ****************************** PROTOTYPES *********************************
+ ******************************************************************************/
+
+/**************************************************************************/ /**
+ * @brief
+ * Initilize the GLIB and DMD interfaces.
+ *
+ * @param[in] void
+ *
+ * @return
+ * void
+ *****************************************************************************/
+void demoUIInit(GLIB_Context_t * context);
+
+/**************************************************************************/ /**
+ * @brief
+ * Update the display with Silicon Labs logo and
+ *application name.
+ *
+ * @param[in] name name of the current application.
+ *
+ * @return
+ * void
+ *****************************************************************************/
+void demoUIDisplayHeader(char * name);
+
+/**************************************************************************/ /**
+ * @brief
+ * Update the display with App image. Bool state only
+ *for now.
+ *
+ * @param[in] on status of App
+ *
+ * @return
+ * void
+ *****************************************************************************/
+void demoUIDisplayApp(bool on);
+
+/**************************************************************************/ /**
+ * @brief
+ * Update the display to show if the bluetooth is
+ *connected to the mobile device.
+ *
+ * @param[in] bool, true if the Light is connected to
+ *mobile device, false otherwise.
+ *
+ * @return
+ * void
+ *****************************************************************************/
+void demoUIDisplayProtocol(demoUIProtocol protocol, bool isConnected);
+
+/**************************************************************************/ /**
+ * @brief
+ * Clear the Lcd screen and display the main screen.
+ *
+ * @param[in] name - application name
+ * @param[in] showPROT1 - show protocol 1 related icon.
+ * @param[in] showPROT2 - show protocol 2 related icon.
+ *
+ * @return
+ * void
+ *****************************************************************************/
+void demoUIClearMainScreen(uint8_t * name);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/display/lcd.cpp b/examples/platform/silabs/SiWx917/display/lcd.cpp
new file mode 100644
index 0000000..6e1f2d2
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/lcd.cpp
@@ -0,0 +1,220 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "demo-ui.h"
+#include "lcd.h"
+
+#include "dmd.h"
+#include "glib.h"
+
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+
+#include "sl_board_control.h"
+
+#define LCD_SIZE 128
+#define QR_CODE_VERSION 4
+#define QR_CODE_MODULE_SIZE 3
+#define QR_CODE_BORDER_SIZE 0
+
+#ifdef QR_CODE_ENABLED
+static uint8_t qrCode[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_CODE_VERSION)];
+static uint8_t workBuffer[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_CODE_VERSION)];
+#endif // QR_CODE_ENABLED
+
+CHIP_ERROR SilabsLCD::Init(uint8_t * name, bool initialState)
+{
+ EMSTATUS status;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ // Check if Name is to long
+ if (name != nullptr)
+ {
+ if (APP_NAME_MAX_LENGTH < strlen((char *) name))
+ {
+ SILABS_LOG("App Name too long");
+ return CHIP_ERROR_INVALID_ARGUMENT;
+ }
+ else
+ {
+ strcpy((char *) mName, (char *) name);
+ }
+ }
+
+ /* Enable the memory lcd */
+ status = sl_board_enable_display();
+ if (status != SL_STATUS_OK)
+ {
+ SILABS_LOG("Board Display enable fail %d", status);
+ err = CHIP_ERROR_INTERNAL;
+ }
+
+ /* Initialize the DMD module for the DISPLAY device driver. */
+ status = DMD_init(0);
+ if (DMD_OK != status)
+ {
+ SILABS_LOG("DMD init failed %d", status);
+ err = CHIP_ERROR_INTERNAL;
+ }
+
+ /* Initialize the glib context */
+ status = GLIB_contextInit(&glibContext);
+ if (GLIB_OK != status)
+ {
+ SILABS_LOG("Glib context init failed %d", status);
+ err = CHIP_ERROR_INTERNAL;
+ }
+
+ glibContext.backgroundColor = White;
+ glibContext.foregroundColor = Black;
+ status = GLIB_clear(&glibContext);
+ if (GLIB_OK != status)
+ {
+ SILABS_LOG("Glib clear failed %d", status);
+ err = CHIP_ERROR_INTERNAL;
+ }
+ demoUIInit(&glibContext);
+
+ dState.mainState = initialState;
+
+ return err;
+}
+
+/* This function is necessary because currently glib.h cannot be used within a C++ context. */
+void * SilabsLCD::Context()
+{
+ return (void *) &glibContext;
+}
+
+int SilabsLCD::Clear()
+{
+ return GLIB_clear(&glibContext);
+}
+
+int SilabsLCD::DrawPixel(void * pContext, int32_t x, int32_t y)
+{
+ return GLIB_drawPixel((GLIB_Context_t *) pContext, x, y);
+}
+
+int SilabsLCD::Update(void)
+{
+ return DMD_updateDisplay();
+}
+
+void SilabsLCD::WriteDemoUI(bool state)
+{
+#ifdef QR_CODE_ENABLED
+ if (mShowQRCode)
+ {
+ mShowQRCode = false;
+ }
+#endif
+ dState.mainState = state;
+ WriteDemoUI();
+}
+
+void SilabsLCD::WriteDemoUI()
+{
+ Clear();
+ if (customUI != nullptr)
+ {
+ customUI(&glibContext);
+ }
+ else
+ {
+ demoUIClearMainScreen(mName);
+ demoUIDisplayApp(dState.mainState);
+ }
+}
+
+void SilabsLCD::SetCustomUI(customUICB cb)
+{
+ customUI = cb;
+}
+
+#ifdef QR_CODE_ENABLED
+void SilabsLCD::WriteQRCode()
+{
+ if (!qrcodegen_encodeText((const char *) mQRCodeBuffer, workBuffer, qrCode, qrcodegen_Ecc_LOW, QR_CODE_VERSION, QR_CODE_VERSION,
+ qrcodegen_Mask_AUTO, true))
+ {
+ SILABS_LOG("qrcodegen_encodeText() failed");
+ return;
+ }
+
+ const int size = qrcodegen_getSize(qrCode);
+
+ GLIB_clear(&glibContext);
+
+ const int displaySize = (2 * QR_CODE_BORDER_SIZE + size) * QR_CODE_MODULE_SIZE;
+ const int displayX = (LCD_SIZE - displaySize) / 2;
+ const int displayY = displayX;
+
+ for (int y = 0; y < size; ++y)
+ {
+ for (int x = 0; x < size; ++x)
+ {
+ if (qrcodegen_getModule(qrCode, x, y))
+ {
+ LCDFillRect(displayX + (QR_CODE_BORDER_SIZE + x) * QR_CODE_MODULE_SIZE,
+ displayY + (QR_CODE_BORDER_SIZE + y) * QR_CODE_MODULE_SIZE, QR_CODE_MODULE_SIZE, QR_CODE_MODULE_SIZE);
+ }
+ }
+ }
+
+ DMD_updateDisplay();
+}
+
+void SilabsLCD::SetQRCode(uint8_t * str, uint32_t size)
+{
+ if (size < chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1)
+ {
+ memcpy(mQRCodeBuffer, str, size);
+ }
+}
+
+void SilabsLCD::ShowQRCode(bool show, bool forceRefresh)
+{
+ if (show != mShowQRCode || forceRefresh)
+ {
+ (show) ? WriteQRCode() : WriteDemoUI();
+ mShowQRCode = show;
+ }
+}
+
+void SilabsLCD::ToggleQRCode(void)
+{
+ (mShowQRCode) ? WriteDemoUI() : WriteQRCode();
+ mShowQRCode = !mShowQRCode;
+}
+
+void SilabsLCD::LCDFillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
+{
+ for (int i = 0; i < h; i++)
+ {
+ for (int j = 0; j < w; j++)
+ {
+ GLIB_drawPixel(&glibContext, x + j, y + i);
+ }
+ }
+}
+#endif // QR_CODE_ENABLED
diff --git a/examples/platform/silabs/SiWx917/display/lcd.h b/examples/platform/silabs/SiWx917/display/lcd.h
new file mode 100644
index 0000000..d375b7a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/lcd.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "AppConfig.h"
+#include "glib.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#include <setup_payload/QRCodeSetupPayloadGenerator.h>
+#endif // QR_CODE_ENABLED
+
+#include "demo-ui.h"
+
+#define MAX_STR_LEN 48
+
+class SilabsLCD
+{
+
+public:
+ typedef void (*customUICB)(GLIB_Context_t * context);
+ CHIP_ERROR Init(uint8_t * name = nullptr, bool initialState = false);
+ void * Context();
+ int Clear(void);
+ int DrawPixel(void * pContext, int32_t x, int32_t y);
+ int Update(void);
+ void WriteDemoUI(bool state);
+ void SetCustomUI(customUICB cb);
+
+#ifdef QR_CODE_ENABLED
+ void SetQRCode(uint8_t * str, uint32_t size);
+ void ShowQRCode(bool show, bool forceRefresh = false);
+ void ToggleQRCode(void);
+#endif
+
+private:
+ typedef struct demoState
+ {
+ bool mainState = false;
+ bool protocol1 = false; /* data */
+ } DemoState_t;
+
+ void WriteQRCode();
+ void WriteDemoUI();
+#ifdef QR_CODE_ENABLED
+ void LCDFillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h);
+ char mQRCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
+ bool mShowQRCode = true;
+#endif
+ GLIB_Context_t glibContext;
+
+#ifdef SL_DEMO_NAME
+ uint8_t mName[] = SL_DEMO_NAME
+#else
+ uint8_t mName[APP_NAME_MAX_LENGTH + 1];
+#endif
+ customUICB customUI = nullptr;
+ DemoState_t dState;
+};
diff --git a/examples/platform/silabs/SiWx917/efr32_utils.cpp b/examples/platform/silabs/SiWx917/efr32_utils.cpp
new file mode 100644
index 0000000..bd2bf77
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/efr32_utils.cpp
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2022 Silabs.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "efr32_utils.h"
+#include "init_efrPlatform.h"
+#include "sl_system_kernel.h"
+
+#include <matter_config.h>
+
+void appError(int err)
+{
+ SILABS_LOG("!!!!!!!!!!!! App Critical Error: %d !!!!!!!!!!!", err);
+ portDISABLE_INTERRUPTS();
+ while (true)
+ ;
+}
+
+void appError(CHIP_ERROR error)
+{
+ appError(static_cast<int>(error.AsInteger()));
+}
diff --git a/examples/platform/silabs/SiWx917/efr32_utils.h b/examples/platform/silabs/SiWx917/efr32_utils.h
new file mode 100644
index 0000000..b0d508d
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/efr32_utils.h
@@ -0,0 +1,38 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2022 Silabs.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// EFR Logging
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void silabsInitLog(void);
+
+void efr32Log(const char * aFormat, ...);
+#define SILABS_LOG(...) efr32Log(__VA_ARGS__);
+void appError(int err);
+
+#ifdef __cplusplus
+}
+
+#include <lib/core/CHIPError.h>
+void appError(CHIP_ERROR error);
+#endif
diff --git a/examples/platform/silabs/SiWx917/init_efrPlatform.cpp b/examples/platform/silabs/SiWx917/init_efrPlatform.cpp
new file mode 100644
index 0000000..993b4fe
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/init_efrPlatform.cpp
@@ -0,0 +1,86 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AppConfig.h"
+#include <lib/support/CHIPPlatformMemory.h>
+#include <platform/CHIPDeviceLayer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <assert.h>
+#include <string.h>
+
+#include <mbedtls/platform.h>
+
+#if CHIP_ENABLE_OPENTHREAD
+#include <openthread-core-config.h>
+#include <openthread/cli.h>
+#include <openthread/config.h>
+#include <openthread/dataset.h>
+#include <openthread/error.h>
+#include <openthread/heap.h>
+#include <openthread/icmp6.h>
+#include <openthread/instance.h>
+#include <openthread/link.h>
+#include <openthread/platform/openthread-system.h>
+#include <openthread/tasklet.h>
+#include <openthread/thread.h>
+#include <utils/uart.h>
+
+#include "platform-efr32.h"
+
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+#include "openthread/heap.h"
+#endif // OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+#endif // CHIP_ENABLE_OPENTHREAD
+
+#include "init_efrPlatform.h"
+#include "sl_component_catalog.h"
+#include "sl_mbedtls.h"
+#include "sl_system_init.h"
+
+#if SL_SYSTEM_VIEW
+#include "SEGGER_SYSVIEW.h"
+#endif
+
+void initAntenna(void);
+
+void init_efrPlatform(void)
+{
+ sl_system_init();
+ sl_mbedtls_init();
+#if SL_SYSTEM_VIEW
+ SEGGER_SYSVIEW_Conf();
+ SEGGER_SYSVIEW_Start();
+#endif
+
+#if SILABS_LOG_ENABLED
+ silabsInitLog();
+#endif
+
+#if CHIP_ENABLE_OPENTHREAD
+ efr32RadioInit();
+ efr32AlarmInit();
+#endif // CHIP_ENABLE_OPENTHREAD
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/init_efrPlatform.h b/examples/platform/silabs/SiWx917/init_efrPlatform.h
new file mode 100644
index 0000000..aeb47b8
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/init_efrPlatform.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*******************************************************************************/
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void init_efrPlatform(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/ldscripts/efr32mg12.ld b/examples/platform/silabs/SiWx917/ldscripts/efr32mg12.ld
new file mode 100644
index 0000000..f9f4f55
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/efr32mg12.ld
@@ -0,0 +1,242 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/***************************************************************************//**
+ * Linker script for Silicon Labs EFR32MG12P devices
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2022 Silicon Laboratories Inc. www.silabs.com</b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 1048576
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 262144
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __copy_table_start__
+ * __copy_table_end__
+ * __zero_table_start__
+ * __zero_table_end__
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __end__
+ * end
+ * __HeapBase
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text :
+ {
+ KEEP(*(.vectors))
+
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ .copy.table :
+ {
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+
+ LONG (__etext)
+ LONG (__data_start__)
+ LONG ((__data_end__ - __data_start__) / 4)
+
+ __copy_table_end__ = .;
+ } > FLASH
+
+ .zero.table :
+ {
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ __zero_table_end__ = .;
+ } > FLASH
+
+ __etext = ALIGN (4);
+
+ .data : AT (__etext)
+ {
+ __data_start__ = .;
+ *(vtable)
+ *(.data*)
+ . = ALIGN (4);
+ PROVIDE (__ram_func_section_start = .);
+ *(.ram)
+ PROVIDE (__ram_func_section_end = .);
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM
+
+ .heap (COPY) :
+ {
+ __HeapBase = .;
+ __end__ = .;
+ end = __end__;
+ _end = __end__;
+ KEEP(*(.heap*))
+ __HeapLimit = .;
+ } > RAM
+
+ __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH);
+
+ /* .stack_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later */
+ .stack_dummy (COPY):
+ {
+ KEEP(*(.stack*))
+ } > RAM
+
+ /* Set stack top to end of RAM, and stack limit move down by
+ * size of stack_dummy section */
+ __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+ PROVIDE(__stack = __StackTop);
+
+ .nvm (DSECT) : {
+ KEEP(*(.simee*))
+ } > FLASH
+
+ /* Last page of flash is reserved for the manufacturing token space */
+ linker_nvm_end = __main_flash_end__ - 2048;
+ linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
+ linker_nvm_size = SIZEOF(.nvm);
+ __nvm3Base = linker_nvm_begin;
+ __attestation_credentials_base = linker_nvm_end;
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/
+ ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !")
+
+ /* Check if FLASH usage exceeds FLASH size */
+ ASSERT( LENGTH(FLASH) >= (__etext), "FLASH memory overflowed !")
+ ASSERT((__etext + SIZEOF(.data)) <= __nvm3Base, "FLASH memory overlapped with NVM section.")
+}
diff --git a/examples/platform/silabs/SiWx917/ldscripts/efr32mg21.ld b/examples/platform/silabs/SiWx917/ldscripts/efr32mg21.ld
new file mode 100644
index 0000000..2c9de0d
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/efr32mg21.ld
@@ -0,0 +1,289 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/***************************************************************************//**
+ * Linker script for Silicon Labs EFR32MG21 devices
+ * @version 5.7.2
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 1048576 - 8192 /* 8K is reserved at top of flash on MG21 */
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 98304
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __copy_table_start__
+ * __copy_table_end__
+ * __zero_table_start__
+ * __zero_table_end__
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __end__
+ * end
+ * __HeapBase
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ * __Vectors_End
+ * __Vectors_Size
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text :
+ {
+ KEEP(*(.vectors))
+ __Vectors_End = .;
+ __Vectors_Size = __Vectors_End - __Vectors;
+ __end__ = .;
+
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ KEEP(*(.application_properties))
+ KEEP(*(.gecko_configuration))
+ KEEP(*(.xo_configuration))
+ KEEP(*(.gatt_header))
+ KEEP(*(.gatt_data))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+
+
+ /* To copy multiple ROM to RAM sections,
+ * uncomment .copy.table section and,
+ * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+ /*
+ .copy.table :
+ {
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+ LONG (__etext)
+ LONG (__data_start__)
+ LONG (__data_end__ - __data_start__)
+ LONG (__etext2)
+ LONG (__data2_start__)
+ LONG (__data2_end__ - __data2_start__)
+ __copy_table_end__ = .;
+ } > FLASH
+ */
+
+ /* To clear multiple BSS sections,
+ * uncomment .zero.table section and,
+ * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+ /*
+ .zero.table :
+ {
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ LONG (__bss_start__)
+ LONG (__bss_end__ - __bss_start__)
+ LONG (__bss2_start__)
+ LONG (__bss2_end__ - __bss2_start__)
+ __zero_table_end__ = .;
+ } > FLASH
+ */
+
+ __etext = .;
+
+ /*******************************************************************/
+ /* Define flash block for BLE-simee & CHIP-nvm3 */
+ /* simee: 9000H (36k) bytes for BLE nvm3 */
+ /* chipNvm3_section: 4000H (16k) bytes for CHIP nvm3. */
+ /* 8K is reserved for OpenThread's NVM which is mapped directly at */
+ /* the top of flash */
+ /*******************************************************************/
+
+ OPENTHREAD_NVM_SIZE = 8192;
+
+ .nvm_dummy (DSECT):
+ {
+ __nvm3_dummy_begin = .;
+ . = ALIGN (8192);
+ __nvm3_dummy_simee = .;
+ KEEP(*(.simee));
+ . = ALIGN (8192);
+ __nvm3_dummy_chip = .;
+ KEEP(*(chipNvm3_section));
+ . = ALIGN (8192);
+ . += OPENTHREAD_NVM_SIZE;
+ . = ALIGN (8192);
+ } > FLASH
+
+ /* Set NVM to end of FLASH */
+ __nvm3Base = LENGTH(FLASH) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_simee - __nvm3_dummy_begin);
+ __nvm3ChipBase = LENGTH(FLASH) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_chip - __nvm3_dummy_begin);
+
+
+ /*******************************************************************/
+
+ .data : AT (__etext)
+ {
+ __data_start__ = .;
+ *(vtable)
+ *(.data*)
+ . = ALIGN (4);
+ PROVIDE (__ram_func_section_start = .);
+ *(.ram)
+ PROVIDE (__ram_func_section_end = .);
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM
+
+ .heap (COPY):
+ {
+ __HeapBase = .;
+ __end__ = .;
+ end = __end__;
+ _end = __end__;
+ KEEP(*(.heap*))
+ __HeapLimit = .;
+ } > RAM
+
+ /* .stack_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later */
+ .stack_dummy (COPY):
+ {
+ KEEP(*(.stack*))
+ } > RAM
+
+ /* Set stack top to end of RAM, and stack limit move down by
+ * size of stack_dummy section */
+ __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+ PROVIDE(__stack = __StackTop);
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+
+
+ /* Check if FLASH usage exceeds FLASH size */
+ ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
+ ASSERT((__etext + SIZEOF(.data)) <= __nvm3Base, "FLASH memory overlapped with NVM section.")
+}
\ No newline at end of file
diff --git a/examples/platform/silabs/SiWx917/ldscripts/efr32mg24.ld b/examples/platform/silabs/SiWx917/ldscripts/efr32mg24.ld
new file mode 100644
index 0000000..b057a9a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/efr32mg24.ld
@@ -0,0 +1,243 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/***************************************************************************//**
+ * @file gcc_EFR32MG24.ld
+ * @brief GNU Linker Script for Cortex-M based device
+ * @version V2.2.0
+ * @date 16. December 2020
+ * Linker script for Silicon Labs EFR32MG24 devices
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2022 Silicon Laboratories, Inc. www.silabs.com </b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08006000, LENGTH = 0x17A000
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __copy_table_start__
+ * __copy_table_end__
+ * __zero_table_start__
+ * __zero_table_end__
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __end__
+ * end
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ * __StackSeal (only if ARMv8-M stack sealing is used)
+ */
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text :
+ {
+ KEEP(*(.vectors))
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ .copy.table :
+ {
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+
+ LONG (__etext)
+ LONG (__data_start__)
+ LONG ((__data_end__ - __data_start__) / 4)
+
+ __copy_table_end__ = .;
+ } > FLASH
+
+ .zero.table :
+ {
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ __zero_table_end__ = .;
+ __etext = ALIGN(4);
+ } > FLASH
+
+ .data : AT (__etext)
+ {
+ __data_start__ = .;
+ *(vtable)
+ *(.data*)
+ . = ALIGN (4);
+ PROVIDE (__ram_func_section_start = .);
+ *(.ram)
+ PROVIDE (__ram_func_section_end = .);
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM AT > RAM
+
+ .heap (COPY):
+ {
+ __HeapBase = .;
+ __end__ = .;
+ end = __end__;
+ _end = __end__;
+ KEEP(*(.heap*))
+ __HeapLimit = .;
+ } > RAM
+
+ __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH);
+
+ /* .stack_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later */
+ .stack_dummy (COPY):
+ {
+ KEEP(*(.stack*))
+ /* KEEP(*(.stackseal*))*/
+ } > RAM
+
+ /* Set stack top to end of RAM, and stack limit move down by
+ * size of stack_dummy section */
+ __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+ PROVIDE(__stack = __StackTop);
+
+ .nvm (DSECT) : {
+ KEEP(*(.simee*))
+ } > FLASH
+
+ /* Last page of flash is reserved for the manufacturing token space */
+ linker_nvm_end = __main_flash_end__ - 8192;
+ linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
+ linker_nvm_size = SIZEOF(.nvm);
+ __nvm3Base = linker_nvm_begin;
+ __attestation_credentials_base = linker_nvm_end;
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/
+ ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !")
+
+ /* Check if FLASH usage exceeds FLASH size */
+ ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
+}
diff --git a/examples/platform/silabs/SiWx917/ldscripts/mgm24.ld b/examples/platform/silabs/SiWx917/ldscripts/mgm24.ld
new file mode 100644
index 0000000..b057a9a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/mgm24.ld
@@ -0,0 +1,243 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/***************************************************************************//**
+ * @file gcc_EFR32MG24.ld
+ * @brief GNU Linker Script for Cortex-M based device
+ * @version V2.2.0
+ * @date 16. December 2020
+ * Linker script for Silicon Labs EFR32MG24 devices
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2022 Silicon Laboratories, Inc. www.silabs.com </b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08006000, LENGTH = 0x17A000
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __copy_table_start__
+ * __copy_table_end__
+ * __zero_table_start__
+ * __zero_table_end__
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __end__
+ * end
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ * __StackSeal (only if ARMv8-M stack sealing is used)
+ */
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text :
+ {
+ KEEP(*(.vectors))
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ .copy.table :
+ {
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+
+ LONG (__etext)
+ LONG (__data_start__)
+ LONG ((__data_end__ - __data_start__) / 4)
+
+ __copy_table_end__ = .;
+ } > FLASH
+
+ .zero.table :
+ {
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ __zero_table_end__ = .;
+ __etext = ALIGN(4);
+ } > FLASH
+
+ .data : AT (__etext)
+ {
+ __data_start__ = .;
+ *(vtable)
+ *(.data*)
+ . = ALIGN (4);
+ PROVIDE (__ram_func_section_start = .);
+ *(.ram)
+ PROVIDE (__ram_func_section_end = .);
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM AT > RAM
+
+ .heap (COPY):
+ {
+ __HeapBase = .;
+ __end__ = .;
+ end = __end__;
+ _end = __end__;
+ KEEP(*(.heap*))
+ __HeapLimit = .;
+ } > RAM
+
+ __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH);
+
+ /* .stack_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later */
+ .stack_dummy (COPY):
+ {
+ KEEP(*(.stack*))
+ /* KEEP(*(.stackseal*))*/
+ } > RAM
+
+ /* Set stack top to end of RAM, and stack limit move down by
+ * size of stack_dummy section */
+ __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+ PROVIDE(__stack = __StackTop);
+
+ .nvm (DSECT) : {
+ KEEP(*(.simee*))
+ } > FLASH
+
+ /* Last page of flash is reserved for the manufacturing token space */
+ linker_nvm_end = __main_flash_end__ - 8192;
+ linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
+ linker_nvm_size = SIZEOF(.nvm);
+ __nvm3Base = linker_nvm_begin;
+ __attestation_credentials_base = linker_nvm_end;
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/
+ ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !")
+
+ /* Check if FLASH usage exceeds FLASH size */
+ ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
+}
diff --git a/examples/platform/silabs/SiWx917/matter_config.cpp b/examples/platform/silabs/SiWx917/matter_config.cpp
new file mode 100644
index 0000000..83e9095
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/matter_config.cpp
@@ -0,0 +1,243 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2022 Silabs.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AppConfig.h"
+#include "OTAConfig.h"
+#include <matter_config.h>
+
+#include <FreeRTOS.h>
+
+#include <mbedtls/platform.h>
+
+#ifdef SL_WIFI
+#include "wfx_host_events.h"
+#endif /* SL_WIFI */
+
+#if PW_RPC_ENABLED
+#include "Rpc.h"
+#endif
+
+#ifdef ENABLE_CHIP_SHELL
+#include "matter_shell.h"
+#endif
+
+#ifdef HEAP_MONITORING
+#include "MemMonitoring.h"
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+
+#include <crypto/CHIPCryptoPAL.h>
+// If building with the EFR32-provided crypto backend, we can use the
+// opaque keystore
+#if CHIP_CRYPTO_PLATFORM
+#include <platform/silabs/EFR32/Efr32PsaOperationalKeystore.h>
+static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeystore;
+#endif
+
+#include "EFR32DeviceDataProvider.h"
+
+#if CHIP_ENABLE_OPENTHREAD
+#include <inet/EndPointStateOpenThread.h>
+#include <openthread/cli.h>
+#include <openthread/dataset.h>
+#include <openthread/error.h>
+#include <openthread/heap.h>
+#include <openthread/icmp6.h>
+#include <openthread/instance.h>
+#include <openthread/link.h>
+#include <openthread/platform/openthread-system.h>
+#include <openthread/tasklet.h>
+#include <openthread/thread.h>
+
+// ================================================================================
+// Matter Networking Callbacks
+// ================================================================================
+void LockOpenThreadTask(void)
+{
+ chip::DeviceLayer::ThreadStackMgr().LockThreadStack();
+}
+
+void UnlockOpenThreadTask(void)
+{
+ chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack();
+}
+
+// ================================================================================
+// EFR32MatterConfig Methods
+// ================================================================================
+
+CHIP_ERROR EFR32MatterConfig::InitOpenThread(void)
+{
+ SILABS_LOG("Initializing OpenThread stack");
+ ReturnErrorOnFailure(ThreadStackMgr().InitThreadStack());
+
+#if CHIP_DEVICE_CONFIG_THREAD_FTD
+ ReturnErrorOnFailure(ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router));
+#else // CHIP_DEVICE_CONFIG_THREAD_FTD
+#if CHIP_DEVICE_CONFIG_ENABLE_SED
+ ReturnErrorOnFailure(ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice));
+#else // CHIP_DEVICE_CONFIG_ENABLE_SED
+ ReturnErrorOnFailure(ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice));
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+#endif // CHIP_DEVICE_CONFIG_THREAD_FTD
+
+ SILABS_LOG("Starting OpenThread task");
+ return ThreadStackMgrImpl().StartThreadTask();
+}
+#endif // CHIP_ENABLE_OPENTHREAD
+
+#if EFR32_OTA_ENABLED
+void EFR32MatterConfig::InitOTARequestorHandler(System::Layer * systemLayer, void * appState)
+{
+ OTAConfig::Init();
+}
+#endif
+
+void EFR32MatterConfig::ConnectivityEventCallback(const ChipDeviceEvent * event, intptr_t arg)
+{
+ // Initialize OTA only when Thread or WiFi connectivity is established
+ if (((event->Type == DeviceEventType::kThreadConnectivityChange) &&
+ (event->ThreadConnectivityChange.Result == kConnectivity_Established)) ||
+ ((event->Type == DeviceEventType::kInternetConnectivityChange) &&
+ (event->InternetConnectivityChange.IPv6 == kConnectivity_Established)))
+ {
+#if EFR32_OTA_ENABLED
+ SILABS_LOG("Scheduling OTA Requestor initialization")
+ chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(OTAConfig::kInitOTARequestorDelaySec),
+ InitOTARequestorHandler, nullptr);
+#endif
+ }
+}
+
+CHIP_ERROR EFR32MatterConfig::InitMatter(const char * appName)
+{
+ CHIP_ERROR err;
+
+ mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree);
+
+ SILABS_LOG("==================================================");
+ SILABS_LOG("%s starting", appName);
+ SILABS_LOG("==================================================");
+
+#if PW_RPC_ENABLED
+ chip::rpc::Init();
+#endif
+
+#ifdef HEAP_MONITORING
+ MemMonitoring::startHeapMonitoring();
+#endif
+ SetDeviceInstanceInfoProvider(&EFR32::EFR32DeviceDataProvider::GetDeviceDataProvider());
+ SetCommissionableDataProvider(&EFR32::EFR32DeviceDataProvider::GetDeviceDataProvider());
+
+ //==============================================
+ // Init Matter Stack
+ //==============================================
+ SILABS_LOG("Init CHIP Stack");
+ // Init Chip memory management before the stack
+ ReturnErrorOnFailure(chip::Platform::MemoryInit());
+ ReturnErrorOnFailure(PlatformMgr().InitChipStack());
+
+ chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(appName);
+
+#if CHIP_ENABLE_OPENTHREAD
+ ReturnErrorOnFailure(InitOpenThread());
+#endif
+
+ // Stop Matter event handling while setting up resources
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+
+ // Create initParams with SDK example defaults here
+ static chip::CommonCaseDeviceServerInitParams initParams;
+
+#if CHIP_CRYPTO_PLATFORM
+ // When building with EFR32 crypto, use the opaque key store
+ // instead of the default (insecure) one.
+ gOperationalKeystore.Init();
+ initParams.operationalKeystore = &gOperationalKeystore;
+#endif
+
+ // Initialize the remaining (not overridden) providers to the SDK example defaults
+ (void) initParams.InitializeStaticResourcesBeforeServerInit();
+
+#if CHIP_ENABLE_OPENTHREAD
+ // Set up OpenThread configuration when OpenThread is included
+ chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
+ nativeParams.lockCb = LockOpenThreadTask;
+ nativeParams.unlockCb = UnlockOpenThreadTask;
+ nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance();
+ initParams.endpointNativeParams = static_cast<void *>(&nativeParams);
+#endif
+
+ // Init Matter Server and Start Event Loop
+ err = chip::Server::GetInstance().Init(initParams);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ ReturnErrorOnFailure(err);
+
+ // OTA Requestor initialization will be triggered by the connectivity events
+ PlatformMgr().AddEventHandler(ConnectivityEventCallback, reinterpret_cast<intptr_t>(nullptr));
+
+ SILABS_LOG("Starting Platform Manager Event Loop");
+ ReturnErrorOnFailure(PlatformMgr().StartEventLoopTask());
+
+#ifdef SL_WIFI
+ InitWiFi();
+#endif
+
+#ifdef ENABLE_CHIP_SHELL
+ chip::startShellTask();
+#endif
+
+ return CHIP_NO_ERROR;
+}
+
+#ifdef SL_WIFI
+void EFR32MatterConfig::InitWiFi(void)
+{
+#ifdef WF200_WIFI
+ // Start wfx bus communication task.
+ wfx_bus_start();
+#ifdef SL_WFX_USE_SECURE_LINK
+ wfx_securelink_task_start(); // start securelink key renegotiation task
+#endif // SL_WFX_USE_SECURE_LINK
+#endif /* WF200_WIFI */
+
+#ifdef RS911X_WIFI
+ /*
+ * Start up any RSI interface stuff
+ * (Not required) - Note that wfx_wifi_start will deal with
+ * starting up a rsi task - which will initialize the SPI interface.
+ */
+#endif
+}
+#endif // SL_WIFI
+
+// ================================================================================
+// FreeRTOS Callbacks
+// ================================================================================
+extern "C" void vApplicationIdleHook(void)
+{
+ // FreeRTOS Idle callback
+
+ // Check CHIP Config nvm3 and repack flash if necessary.
+ Internal::SILABSConfig::RepackNvm3Flash();
+}
diff --git a/examples/platform/silabs/SiWx917/matter_config.h b/examples/platform/silabs/SiWx917/matter_config.h
new file mode 100644
index 0000000..e0af603
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/matter_config.h
@@ -0,0 +1,35 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2022 Silabs.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <lib/support/CHIPMem.h>
+#include <lib/support/CHIPPlatformMemory.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/KeyValueStoreManager.h>
+
+class EFR32MatterConfig
+{
+public:
+ static CHIP_ERROR InitMatter(const char * appName);
+
+private:
+ static CHIP_ERROR InitOpenThread(void);
+ static void InitWiFi(void);
+ static void ConnectivityEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+ static void InitOTARequestorHandler(chip::System::Layer * systemLayer, void * appState);
+};
diff --git a/examples/platform/silabs/SiWx917/project_include/OpenThreadConfig.h b/examples/platform/silabs/SiWx917/project_include/OpenThreadConfig.h
new file mode 100644
index 0000000..dccf3c8
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/project_include/OpenThreadConfig.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Overrides to default OpenThread configuration.
+ *
+ */
+
+#pragma once
+
+#include <em_device.h>
+
+// Disable the SiLabs-supplied OpenThread logging facilities and use
+// the facilities provided by the Device Layer (see
+// src/platform/silabs/Logging.cpp).
+#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_APP
+
+// Turn on a moderate level of logging in OpenThread
+// Enable use of external heap allocator (calloc/free) for OpenThread.
+#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1
+
+// EFR32MG21A020F1024IM32 has 96k of RAM. Reduce the number of buffers to
+// conserve RAM for this Series 2 part.
+#if defined(EFR32MG21)
+#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 22
+#define OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE 512
+#define OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE 512
+#endif
+
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
+#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 1
+
+#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1
+#define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1
+#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1
+
+// disable unused features
+#define OPENTHREAD_CONFIG_COAP_API_ENABLE 0
+#define OPENTHREAD_CONFIG_JOINER_ENABLE 0
+#define OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 0
+#define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0
+#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0
+#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0
+#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0
+#define OPENTHREAD_CONFIG_TCP_ENABLE 0
+
+// Support udp multicast by enabling Multicast Listener Registration (MLR)
+#define OPENTHREAD_CONFIG_MLR_ENABLE 1
+
+// Define as 1 to stay awake between fragments while transmitting a large packet,
+// and to stay awake after receiving a packet with frame pending set to true.
+#define OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS 1
+
+// Use the SiLabs-supplied default platform configuration for remainder
+// of OpenThread config options.
+//
+// NB: This file gets included during the build of OpenThread. Hence
+// it cannot use "openthread" in the path to the included file.
+//
+#include "openthread-core-efr32-config.h"
diff --git a/examples/platform/silabs/SiWx917/pw_sys_io/BUILD.gn b/examples/platform/silabs/SiWx917/pw_sys_io/BUILD.gn
new file mode 100644
index 0000000..722d2a7
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/pw_sys_io/BUILD.gn
@@ -0,0 +1,39 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pw_build/target_types.gni")
+
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+
+config("default_config") {
+ include_dirs = [ "public" ]
+}
+
+pw_source_set("pw_sys_io_efr32") {
+ sources = [ "sys_io_efr32.cc" ]
+
+ deps = [
+ "$dir_pw_sys_io:default_putget_bytes",
+ "$dir_pw_sys_io:facade",
+ ]
+
+ cflags = [ "-Wconversion" ]
+
+ public_configs = [ ":default_config" ]
+
+ include_dirs = [ "${examples_plat_dir}" ]
+}
diff --git a/examples/platform/silabs/SiWx917/pw_sys_io/public/pw_sys_io_efr32/init.h b/examples/platform/silabs/SiWx917/pw_sys_io/public/pw_sys_io_efr32/init.h
new file mode 100644
index 0000000..f11f5e9
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/pw_sys_io/public/pw_sys_io_efr32/init.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "pw_preprocessor/util.h"
+
+PW_EXTERN_C_START
+
+// The actual implement of PreMainInit() in sys_io_BACKEND.
+void pw_sys_io_Init();
+
+PW_EXTERN_C_END
diff --git a/examples/platform/silabs/SiWx917/pw_sys_io/sys_io_efr32.cc b/examples/platform/silabs/SiWx917/pw_sys_io/sys_io_efr32.cc
new file mode 100644
index 0000000..4bc7d98
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/pw_sys_io/sys_io_efr32.cc
@@ -0,0 +1,81 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pw_sys_io/sys_io.h"
+#include <cassert>
+#include <cinttypes>
+#include <stdio.h>
+#include <string.h>
+
+#include "uart.h"
+
+int16_t console_getchar(char * chr)
+{
+ int16_t retVal = 0;
+
+ // Busy wait for pw_rcp reads
+ while (retVal == 0)
+ {
+ retVal = uartConsoleRead(chr, 1);
+ }
+ return retVal;
+}
+
+int16_t console_putchar(const char * chr)
+{
+ return uartConsoleWrite(chr, 1);
+}
+
+extern "C" void pw_sys_io_Init()
+{
+ uartConsoleInit();
+}
+
+namespace pw::sys_io {
+
+Status ReadByte(std::byte * dest)
+{
+ if (!dest)
+ return Status::InvalidArgument();
+
+ int16_t ret = console_getchar(reinterpret_cast<char *>(dest));
+ return ret < 0 ? Status::FailedPrecondition() : OkStatus();
+}
+
+Status WriteByte(std::byte b)
+{
+ int16_t ret = console_putchar(reinterpret_cast<const char *>(&b));
+ return ret < 0 ? Status::FailedPrecondition() : OkStatus();
+}
+
+// Writes a string using pw::sys_io, and add newline characters at the end.
+StatusWithSize WriteLine(const std::string_view & s)
+{
+ size_t chars_written = 0;
+ StatusWithSize result = WriteBytes(pw::as_bytes(pw::span(s)));
+ if (!result.ok())
+ {
+ return result;
+ }
+ chars_written += result.size();
+ result = WriteBytes(pw::as_bytes(pw::span("\r\n", 2)));
+ chars_written += result.size();
+
+ return StatusWithSize(result.status(), chars_written);
+}
+
+} // namespace pw::sys_io
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/efx_spi.c b/examples/platform/silabs/SiWx917/rs911x/hal/efx_spi.c
new file mode 100644
index 0000000..f01cac3
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/efx_spi.c
@@ -0,0 +1,324 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Includes
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dmadrv.h"
+#include "em_chip.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_device.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#if defined(EFR32MG12)
+#include "em_usart.h"
+#elif defined(EFR32MG24)
+#include "em_eusart.h"
+#endif
+#include "spidrv.h"
+
+#include "gpiointerrupt.h"
+#include "sl_device_init_clocks.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+#include "rsi_board_configuration.h"
+#include "rsi_driver.h"
+#include "sl_device_init_dpll.h"
+#include "sl_device_init_hfxo.h"
+
+StaticSemaphore_t xEfxSpiIntfSemaBuffer;
+static SemaphoreHandle_t spi_sem;
+
+#if defined(EFR32MG12)
+#include "sl_spidrv_exp_config.h"
+extern SPIDRV_Handle_t sl_spidrv_exp_handle;
+#endif
+
+#if defined(EFR32MG24)
+#include "sl_spidrv_eusart_exp_config.h"
+extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle;
+#endif
+
+static unsigned int tx_dma_channel;
+static unsigned int rx_dma_channel;
+
+static uint32_t dummy_data; /* Used for DMA - when results don't matter */
+extern void rsi_gpio_irq_cb(uint8_t irqnum);
+//#define RS911X_USE_LDMA
+
+/********************************************************
+ * @fn sl_wfx_host_gpio_init(void)
+ * @brief
+ * Deal with the PINS that are not associated with SPI -
+ * Ie. RESET, Wakeup
+ * @return
+ * None
+ **********************************************************/
+void sl_wfx_host_gpio_init(void)
+{
+ // Enable GPIO clock.
+ CMU_ClockEnable(cmuClock_GPIO, true);
+
+ GPIO_PinModeSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin, gpioModePushPull, PINOUT_SET);
+ GPIO_PinModeSet(WFX_SLEEP_CONFIRM_PIN.port, WFX_SLEEP_CONFIRM_PIN.pin, gpioModePushPull, PINOUT_CLEAR);
+
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+
+ // Set up interrupt based callback function - trigger on both edges.
+ GPIOINT_Init();
+ GPIO_PinModeSet(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin, gpioModeInputPull, PINOUT_CLEAR);
+ GPIO_ExtIntConfig(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin, SL_WFX_HOST_PINOUT_SPI_IRQ, true, false, true);
+ GPIOINT_CallbackRegister(SL_WFX_HOST_PINOUT_SPI_IRQ, rsi_gpio_irq_cb);
+ GPIO_IntDisable(1 << SL_WFX_HOST_PINOUT_SPI_IRQ); /* Will be enabled by RSI */
+
+ // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!)
+ NVIC_SetPriority(GPIO_EVEN_IRQn, WFX_SPI_NVIC_PRIORITY);
+ NVIC_SetPriority(GPIO_ODD_IRQn, WFX_SPI_NVIC_PRIORITY);
+}
+
+/*****************************************************************
+ * @fn void sl_wfx_host_reset_chip(void)
+ * @brief
+ * To reset the WiFi CHIP
+ * @return
+ * None
+ ****************************************************************/
+void sl_wfx_host_reset_chip(void)
+{
+ // Pull it low for at least 1 ms to issue a reset sequence
+ GPIO_PinOutClear(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+
+ // Delay for 10ms
+ vTaskDelay(pdMS_TO_TICKS(10));
+
+ // Hold pin high to get chip out of reset
+ GPIO_PinOutSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+
+ // Delay for 3ms
+ vTaskDelay(pdMS_TO_TICKS(3));
+}
+
+/*****************************************************************
+ * @fn void rsi_hal_board_init(void)
+ * @brief
+ * Initialize the board
+ * @return
+ * None
+ ****************************************************************/
+void rsi_hal_board_init(void)
+{
+ spi_sem = xSemaphoreCreateBinaryStatic(&xEfxSpiIntfSemaBuffer);
+ xSemaphoreGive(spi_sem);
+
+ /* Assign DMA channel from Handle*/
+#if defined(EFR32MG12)
+ /* MG12 + rs9116 combination uses USART driver */
+ tx_dma_channel = sl_spidrv_exp_handle->txDMACh;
+ rx_dma_channel = sl_spidrv_exp_handle->rxDMACh;
+
+#elif defined(EFR32MG24)
+ /* MG24 + rs9116 combination uses EUSART driver */
+ tx_dma_channel = sl_spidrv_eusart_exp_handle->txDMACh;
+ rx_dma_channel = sl_spidrv_eusart_exp_handle->rxDMACh;
+#endif
+
+ /* GPIO INIT of MG12 & MG24 : Reset, Wakeup, Interrupt */
+ WFX_RSI_LOG("RSI_HAL: init GPIO");
+ sl_wfx_host_gpio_init();
+
+ /* Reset of Wifi chip */
+ WFX_RSI_LOG("RSI_HAL: Reset Wifi");
+ sl_wfx_host_reset_chip();
+ WFX_RSI_LOG("RSI_HAL: Init done");
+}
+
+/*****************************************************************************
+ *@fn static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void *userParam)
+ *
+ *@brief
+ * complete dma
+ *
+ * @param[in] channel:
+ * @param[in] sequenceNO: sequence number
+ * @param[in] userParam :user parameter
+ *
+ * @return
+ * None
+ ******************************************************************************/
+static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void * userParam)
+{
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ // uint8_t *buf = (void *)userParam;
+
+ (void) channel;
+ (void) sequenceNo;
+ (void) userParam;
+
+ // WFX_RSI_LOG ("SPI: DMA done [%x,%x,%x,%x]", buf [0], buf [1], buf [2], buf [3]);
+ xSemaphoreGiveFromISR(spi_sem, &xHigherPriorityTaskWoken);
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+
+ return true;
+}
+
+/*************************************************************
+ * @fn static void receiveDMA(uint8_t *rx_buf, uint16_t xlen)
+ * @brief
+ * RX buf was specified
+ * TX buf was not specified by caller - so we
+ * transmit dummy data (typically 0)
+ * @param[in] rx_buf:
+ * @param[in] xlen:
+ * @return
+ * None
+ *******************************************************************/
+static void receiveDMA(uint8_t * rx_buf, uint16_t xlen)
+{
+ /*
+ * The caller wants to receive data -
+ * The xmit can be dummy data (no src increment for tx)
+ */
+ dummy_data = 0;
+ DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, (void *) rx_buf, (void *) &(MY_USART->RXDATA), true, xlen,
+ dmadrvDataSize1, rx_dma_complete, NULL);
+
+ // Start transmit DMA.
+ DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) &(dummy_data), false, xlen,
+ dmadrvDataSize1, NULL, NULL);
+}
+
+/*****************************************************************************
+ *@fn static void transmitDMA(void *rx_buf, void *tx_buf, uint8_t xlen)
+ *@brief
+ * we have a tx_buf. There are some instances where
+ * a rx_buf is not specified. If one is specified then
+ * the caller wants results (auto increment src)
+ * @param[in] rx_buf:
+ * @param[in] tx_buf:
+ * @param[in] xlen:
+ * @return
+ * None
+ ******************************************************************************/
+static void transmitDMA(uint8_t * rx_buf, uint8_t * tx_buf, uint16_t xlen)
+{
+ void * buf;
+ bool srcinc;
+ /*
+ * we have a tx_buf. There are some instances where
+ * a rx_buf is not specified. If one is specified then
+ * the caller wants results (auto increment src)
+ * TODO - the caller specified 8/32 bit - we should use this
+ * instead of dmadrvDataSize1 always
+ */
+ if (rx_buf == NULL)
+ {
+ buf = &dummy_data;
+ srcinc = false;
+ }
+ else
+ {
+ buf = rx_buf;
+ srcinc = true;
+ /* DEBUG */ rx_buf[0] = 0xAA;
+ rx_buf[1] = 0x55;
+ }
+ DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, buf, (void *) &(MY_USART->RXDATA), srcinc, xlen, dmadrvDataSize1,
+ rx_dma_complete, buf);
+ // Start transmit DMA.
+ DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) tx_buf, true, xlen,
+ dmadrvDataSize1, NULL, NULL);
+}
+
+/*********************************************************************
+ * @fn int16_t rsi_spi_transfer(uint8_t *tx_buf, uint8_t *rx_buf, uint16_t xlen, uint8_t mode)
+ * @brief
+ * Do a SPI transfer - Mode is 8/16 bit - But every 8 bit is aligned
+ * @param[in] tx_buf:
+ * @param[in] rx_buf:
+ * @param[in] xlen:
+ * @param[in] mode:
+ * @return
+ * None
+ **************************************************************************/
+int16_t rsi_spi_transfer(uint8_t * tx_buf, uint8_t * rx_buf, uint16_t xlen, uint8_t mode)
+{
+ // WFX_RSI_LOG ("SPI: Xfer: tx=%x,rx=%x,len=%d",(uint32_t)tx_buf, (uint32_t)rx_buf, xlen);
+ if (xlen > MIN_XLEN)
+ {
+ MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+ if (xSemaphoreTake(spi_sem, portMAX_DELAY) != pdTRUE)
+ {
+ return RSI_FALSE;
+ }
+ if (tx_buf == NULL)
+ {
+ receiveDMA(rx_buf, xlen);
+ }
+ else
+ {
+ transmitDMA(rx_buf, tx_buf, xlen);
+ }
+
+ /*
+ * receiveDMA() and transmitDMA() are asynchronous
+ * Our application design assumes that this function is synchronous
+ * To make it synchronous, we wait to re-acquire the semaphore before exiting this function
+ * rx_dma_complete() gives back the semaphore when the SPI transfer is done
+ */
+ if (xSemaphoreTake(spi_sem, pdMS_TO_TICKS(RSI_SEM_BLOCK_MIN_TIMER_VALUE_MS)) == pdTRUE)
+ {
+ // Transfer complete
+ // Give back the semaphore before exiting, so that it may be re-acquired
+ // in this function, just before the next transfer
+ xSemaphoreGive(spi_sem);
+ }
+ // Temporary patch
+ // Sometimes the xSemaphoreTake() above is getting stuck indefinitely
+ // As a workaround, if the transfer is not done within RSI_SEM_BLOCK_MIN_TIMER_VALUE_MS
+ // stop and start it again
+ // No need to re-acquire the semaphore since this is the function that acquired it
+ // TODO: Remove this after a permanent solution is found to the problem of the transfer getting stuck
+ else
+ {
+ uint32_t ldma_flags = 0;
+ uint32_t rem_len = 0;
+ rem_len = LDMA_TransferRemainingCount(RSI_LDMA_TRANSFER_CHANNEL_NUM);
+ LDMA_StopTransfer(RSI_LDMA_TRANSFER_CHANNEL_NUM);
+ ldma_flags = LDMA_IntGet();
+ LDMA_IntClear(ldma_flags);
+ receiveDMA(rx_buf, rem_len);
+ if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE)
+ {
+ xSemaphoreGive(spi_sem);
+ }
+ }
+ }
+
+ return RSI_ERROR_NONE;
+}
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_board_configuration.h b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_board_configuration.h
new file mode 100644
index 0000000..204e751
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_board_configuration.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _RSI_BOARD_CONFIGURATION_H_
+#define _RSI_BOARD_CONFIGURATION_H_
+
+typedef struct
+{
+ unsigned char port;
+ unsigned char pin;
+} rsi_pin_t;
+
+#define PIN(port_id, pin_id) \
+ (rsi_pin_t) { .port = gpioPort##port_id, .pin = pin_id }
+
+#if defined(EFR32MG12_BRD4161A) || defined(BRD4161A) || defined(EFR32MG12_BRD4162A) || defined(BRD4162A) || \
+ defined(EFR32MG12_BRD4163A) || defined(BRD4163A) || defined(EFR32MG12_BRD4164A) || defined(BRD4164A) || \
+ defined(EFR32MG12_BRD4170A) || defined(BRD4170A)
+// BRD4161-63-64 are pin to pin compatible for SPI
+#include "brd4161a.h"
+#elif defined(EFR32MG24_BRD4186C) || defined(BRD4186C)
+#include "brd4186c.h"
+#elif defined(EFR32MG24_BRD4187C) || defined(BRD4187C)
+#include "brd4187c.h"
+#else
+#error "Need SPI Pins"
+#endif /* EFR32MG12_BRD4161A */
+
+#endif /* _RSI_BOARD_CONFIGURATION_H_ */
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal.h b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal.h
new file mode 100644
index 0000000..4e19543
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal.h
@@ -0,0 +1,111 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HAL_RSI_HAL_H_
+#define _HAL_RSI_HAL_H_
+#include "rsi_board_configuration.h"
+
+#define RSI_HAL_NO_COM_PORT /* This will be done by the project */
+
+/* Should be enums */
+#define RSI_HAL_RESET_PIN 0
+#define RSI_HAL_MODULE_INTERRUPT 1
+#define RSI_HAL_SLEEP_CONFIRM_PIN 2
+#define RSI_HAL_WAKEUP_INDICATION_PIN 3
+#define RSI_HAL_MODULE_INTERRUPT_PIN 4
+
+//! Timer related macros
+//! Macro to configure timer type in single shot
+#define RSI_HAL_TIMER_TYPE_SINGLE_SHOT 0
+
+// Macro to configure timer type in periodic
+#define RSI_HAL_TIMER_TYPE_PERIODIC 1
+
+// Macro to configure timer in micro seconds mode
+#define RSI_HAL_TIMER_MODE_MICRO 0
+
+// Macro to configure timer in milli seconds mode
+#define RSI_HAL_TIMER_MODE_MILLI 1
+
+//! GPIO Pins related Macros
+//! Macro to configure GPIO in output mode
+#define RSI_HAL_GPIO_OUTPUT_MODE 1
+
+// Macro to configure GPIO in input mode
+#define RSI_HAL_GPIO_INPUT_MODE 0
+
+// Macro to drive low value on GPIO
+#define RSI_HAL_GPIO_LOW 0
+
+// Macro to drive high value on GPIO
+#define RSI_HAL_GPIO_HIGH 1
+
+// Macro to drive LDMA channel number
+#define RSI_LDMA_TRANSFER_CHANNEL_NUM 3
+
+// Macro to drive semaphore block minimun timer in milli seconds
+#define RSI_SEM_BLOCK_MIN_TIMER_VALUE_MS 50
+
+/******************************************************
+ * * Function Declarations
+ * ******************************************************/
+
+void rsi_hal_board_init(void);
+void rsi_switch_to_high_clk_freq(void);
+void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void));
+void rsi_hal_intr_mask(void);
+void rsi_hal_intr_unmask(void);
+void rsi_hal_intr_clear(void);
+uint8_t rsi_hal_intr_pin_status(void);
+void rsi_hal_config_gpio(uint8_t gpio_number, uint8_t mode, uint8_t value);
+void rsi_hal_set_gpio(uint8_t gpio_number);
+uint8_t rsi_hal_get_gpio(uint8_t gpio_number);
+void rsi_hal_clear_gpio(uint8_t gpio_number);
+int16_t rsi_spi_transfer(uint8_t * tx_buff, uint8_t * rx_buff, uint16_t transfer_length, uint8_t mode);
+int16_t rsi_uart_send(uint8_t * ptrBuf, uint16_t bufLen);
+int16_t rsi_uart_recv(uint8_t * ptrBuf, uint16_t bufLen);
+int16_t rsi_com_port_send(uint8_t * ptrBuf, uint16_t bufLen);
+int16_t rsi_com_port_receive(uint8_t * ptrBuf, uint16_t bufLen);
+uint32_t rsi_get_random_number(void);
+int32_t rsi_timer_start(uint8_t timer_node, uint8_t mode, uint8_t type, uint32_t duration, void (*rsi_timer_expiry_handler)(void));
+int32_t rsi_timer_stop(uint8_t timer_node);
+uint32_t rsi_timer_read(uint8_t timer_node);
+void rsi_delay_us(uint32_t delay_us);
+void rsi_delay_ms(uint32_t delay_ms);
+uint32_t rsi_hal_gettickcount(void);
+void SysTick_Handler(void);
+
+void rsi_interrupt_handler(void);
+void ABRD(void);
+
+void Error_Handler(void);
+
+/* RTC Related API's */
+uint32_t rsi_rtc_get_time(void);
+int32_t rsi_rtc_set_time(uint32_t time);
+/* End - RTC Related API's */
+
+#ifdef LOGGING_STATS
+void rsi_hal_log_stats_intr_config(void (*rsi_give_wakeup_indication)());
+#endif /* LOGGING_STATS */
+#ifdef RSI_WITH_OS
+void rsi_os_delay_ms(uint32_t delay_ms);
+void PORTD_IRQHandler(void);
+
+#endif /* RSI_WITH_OS */
+
+#endif
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_interrupt.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_interrupt.c
new file mode 100644
index 0000000..40e4189
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_interrupt.c
@@ -0,0 +1,161 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dmadrv.h"
+#include "em_chip.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_device.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+#include "sl_device_init_clocks.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+#include "rsi_board_configuration.h"
+#include "rsi_driver.h"
+
+typedef void (*UserIntCallBack_t)(void);
+UserIntCallBack_t call_back, gpio_callback;
+#ifdef LOGGING_STATS
+uint8_t current_pin_set, prev_pin_set;
+#endif /* LOGGING_STATS */
+
+/* ARGSUSED */
+void rsi_gpio_irq_cb(uint8_t irqnum)
+{
+
+ // WFX_RSI_LOG ("RSI: Got Int=%d", irqnum)
+ if (irqnum != SL_WFX_HOST_PINOUT_SPI_IRQ)
+ return;
+ GPIO_IntClear(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+
+ // WFX_RSI_LOG ("Got SPI intr, cb=%x", (uint32_t)call_back);
+ if (call_back != NULL)
+ (*call_back)();
+}
+
+/*===================================================*/
+/**
+ * @fn void rsi_hal_intr_config(void (* rsi_interrupt_handler)())
+ * @brief Starts and enables the SPI interrupt
+ * @param[in] rsi_interrupt_handler() ,call back function to handle interrupt
+ * @param[out] none
+ * @return none
+ * @description This HAL API should contain the code to initialize the register/pins
+ * related to interrupts and enable the interrupts.
+ */
+void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void))
+{
+ call_back = rsi_interrupt_handler;
+ WFX_RSI_LOG("RSI:Set SPI intr CB to=%x", (uint32_t) call_back);
+}
+
+/*===================================================*/
+/**
+ * @fn void rsi_hal_log_stats_intr_config(void (* rsi_give_wakeup_indication)())
+ * @brief Checks the interrupt and map/set gpio callback function
+ * @param[in] rsi_give_wakeup_indication() ,gpio call back function to handle interrupt
+ * @param[out] none
+ * @return none
+ * @description This HAL API should contain the code
+ * related to mapping of gpio callback function.
+ */
+#ifdef LOGGING_STATS
+void rsi_hal_log_stats_intr_config(void (*rsi_give_wakeup_indication)())
+{
+ gpio_callback = rsi_give_wakeup_indication;
+}
+#endif
+
+/*===================================================*/
+/**
+ * @fn void rsi_hal_intr_mask(void)
+ * @brief Disables the SPI Interrupt
+ * @param[in] none
+ * @param[out] none
+ * @return none
+ * @description This HAL API should contain the code to mask/disable interrupts.
+ */
+void rsi_hal_intr_mask(void)
+{
+ // WFX_RSI_LOG ("RSI:Disable IRQ");
+ // NVIC_DisableIRQ(GPIO_ODD_IRQn);
+ GPIO_IntDisable(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+}
+
+/*===================================================*/
+/**
+ * @fn void rsi_hal_intr_unmask(void)
+ * @brief Enables the SPI interrupt
+ * @param[in] none
+ * @param[out] none
+ * @return none
+ * @description This HAL API should contain the code to enable interrupts.
+ */
+void rsi_hal_intr_unmask(void)
+{
+ // Unmask/Enable the interrupt
+ NVIC_EnableIRQ(GPIO_ODD_IRQn);
+ NVIC_EnableIRQ(GPIO_EVEN_IRQn);
+ GPIO_IntEnable(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+ // WFX_RSI_LOG ("RSI:Enable IRQ (mask=%x)", GPIO_IntGetEnabled ());
+}
+
+/*===================================================*/
+/**
+ * @fn void rsi_hal_intr_clear(void)
+ * @brief Clears the pending interrupt
+ * @param[in] none
+ * @param[out] none
+ * @return none
+ * @description This HAL API should contain the code to clear the handled interrupts.
+ */
+void rsi_hal_intr_clear(void)
+{
+ GPIO_IntClear(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+}
+
+/*===================================================*/
+/**
+ * @fn void rsi_hal_intr_pin_status(void)
+ * @brief Checks the SPI interrupt at pin level
+ * @param[in] none
+ * @param[out] uint8_t, interrupt status
+ * @return none
+ * @description This API is used to check interrupt pin status(pin level whether it is high/low).
+ */
+uint8_t rsi_hal_intr_pin_status(void)
+{
+ uint32_t mask;
+ // Return interrupt pin status(high(1) /low (0))
+ mask = GPIO_PinInGet(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin);
+
+ return !!mask;
+}
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_ioports.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_ioports.c
new file mode 100644
index 0000000..1ff5bc5
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_ioports.c
@@ -0,0 +1,141 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dmadrv.h"
+#include "em_chip.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_device.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+#include "sl_device_init_clocks.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+#include "rsi_board_configuration.h"
+#include "rsi_driver.h"
+
+/*===========================================================*/
+/**
+ * @fn void rsi_hal_config_gpio(uint8_t gpio_number,uint8_t mode,uint8_t value)
+ * @brief Configures gpio pin in output mode,with a value
+ * @param[in] uint8_t gpio_number, gpio pin number to be configured
+ * @param[in] uint8_t mode , input/output mode of the gpio pin to configure
+ * 0 - input mode
+ * 1 - output mode
+ * @param[in] uint8_t value, default value to be driven if gpio is configured in output mode
+ * 0 - low
+ * 1 - high
+ * @param[out] none
+ * @return none
+ * @description This API is used to configure host gpio pin in output mode.
+ */
+void rsi_hal_config_gpio(uint8_t gpio_number, uint8_t mode, uint8_t value)
+{
+
+ CMU_ClockEnable(cmuClock_GPIO, true);
+
+ // WFX_RSI_LOG ("RSI: CFG GPIO: 0x%x", gpio_number);
+ switch (gpio_number)
+ {
+ case RSI_HAL_RESET_PIN:
+ GPIO_PinModeSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin, gpioModePushPull, PINOUT_SET);
+ break;
+ default:
+ break;
+ }
+}
+
+/*===========================================================*/
+/**
+ * @fn void rsi_hal_set_gpio(uint8_t gpio_number)
+ * @brief Makes/drives the gpio value high
+ * @param[in] uint8_t gpio_number, gpio pin number
+ * @param[out] none
+ * @return none
+ * @description This API is used to drives or makes the host gpio value high.
+ */
+void rsi_hal_set_gpio(uint8_t gpio_number)
+{
+ // WFX_RSI_LOG ("RSI: SET GPIO: 0x%x", gpio_number);
+ switch (gpio_number)
+ {
+ case RSI_HAL_RESET_PIN:
+ GPIO_PinModeSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin, gpioModeWiredOrPullDown, PINOUT_SET);
+ break;
+ default:
+ break;
+ }
+}
+
+/*===========================================================*/
+/**
+ * @fn uint8_t rsi_hal_get_gpio(void)
+ * @brief get the gpio pin value
+ * @param[in] uint8_t gpio_number, gpio pin number
+ * @param[out] none
+ * @return gpio pin value
+ * @description This API is used to configure get the gpio pin value.
+ */
+uint8_t rsi_hal_get_gpio(uint8_t gpio_number)
+{
+ // WFX_RSI_LOG ("RSI: GET GPIO: 0x%x", gpio_number);
+ switch (gpio_number)
+ {
+ case RSI_HAL_RESET_PIN:
+ return GPIO_PinInGet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+ case RSI_HAL_MODULE_INTERRUPT_PIN:
+ return GPIO_PinInGet(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*===========================================================*/
+/**
+ * @fn void rsi_hal_set_gpio(uint8_t gpio_number)
+ * @brief Makes/drives the gpio value to low
+ * @param[in] uint8_t gpio_number, gpio pin number
+ * @param[out] none
+ * @return none
+ * @description This API is used to drives or makes the host gpio value low.
+ */
+void rsi_hal_clear_gpio(uint8_t gpio_number)
+{
+ // WFX_RSI_LOG ("RSI: CLR GPIO: 0x%x", gpio_number);
+ switch (gpio_number)
+ {
+ case RSI_HAL_RESET_PIN:
+ return GPIO_PinOutClear(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+ default:
+ break;
+ }
+}
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_rtc.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_rtc.c
new file mode 100644
index 0000000..f57d47a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_rtc.c
@@ -0,0 +1,326 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Includes
+ */
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_rtcc.h"
+#include "sl_sleeptimer_config.h"
+#include "sl_status.h"
+#include <stdlib.h>
+#include <time.h>
+
+#define ZONE0 0
+#define CH_SELECTOR 1u
+#define RTC_DEFAULT_COUNTER_VALUE 0u
+#define RSI_RTC_FREQ_VALUE 0
+#define TIME_ZONE_OFFSET 0u
+
+#define SLEEPTIMER_EVENT_OF (0x01)
+#define SLEEPTIMER_EVENT_COMP (0x02)
+#define SLEEPTIMER_ENUM(name) \
+ typedef uint8_t name; \
+ enum name##_enum
+#define TIME_UNIX_EPOCH (1970u)
+#define TIME_NTP_EPOCH (1900u)
+#define TIME_ZIGBEE_EPOCH (2000u)
+#define TIME_NTP_UNIX_EPOCH_DIFF (TIME_UNIX_EPOCH - TIME_NTP_EPOCH)
+#define TIME_ZIGBEE_UNIX_EPOCH_DIFF (TIME_ZIGBEE_EPOCH - TIME_UNIX_EPOCH)
+#define TIME_DAY_COUNT_NTP_TO_UNIX_EPOCH (TIME_NTP_UNIX_EPOCH_DIFF * 365u + 17u) ///< 70 years and 17 leap days
+#define TIME_DAY_COUNT_ZIGBEE_TO_UNIX_EPOCH (TIME_ZIGBEE_UNIX_EPOCH_DIFF * 365u + 7u) ///< 30 years and 7 leap days
+#define TIME_SEC_PER_DAY (60u * 60u * 24u)
+#define TIME_NTP_EPOCH_OFFSET_SEC (TIME_DAY_COUNT_NTP_TO_UNIX_EPOCH * TIME_SEC_PER_DAY)
+#define TIME_ZIGBEE_EPOCH_OFFSET_SEC (TIME_DAY_COUNT_ZIGBEE_TO_UNIX_EPOCH * TIME_SEC_PER_DAY)
+#define TIME_DAY_PER_YEAR (365u)
+#define TIME_SEC_PER_YEAR (TIME_SEC_PER_DAY * TIME_DAY_PER_YEAR)
+#define TIME_UNIX_TIMESTAMP_MAX (0x7FFFFFFF)
+
+/// Time zone offset from UTC(second).
+typedef int32_t sl_sleeptimer_time_zone_offset_t;
+/// Timestamp, wall clock time in seconds.
+typedef uint32_t sl_sleeptimer_timestamp_t;
+/// @brief Time Format.
+SLEEPTIMER_ENUM(sl_sleeptimer_time_format_t){
+ TIME_FORMAT_UNIX = 0, ///< Number of seconds since January 1, 1970, 00:00.
+ ///< Type is signed, so represented on 31 bit.
+ TIME_FORMAT_NTP = 1, ///< Number of seconds since January 1, 1900, 00:00.
+ ///< Type is unsigned, so represented on 32 bit.
+ TIME_FORMAT_ZIGBEE_CLUSTER = 2, ///< Number of seconds since January 1, 2000, 00:00. Type is
+ ///< unsigned, so represented on 32 bit.
+};
+
+// Initialization flag.
+static bool is_sleeptimer_initialized = false;
+// Timer frequency in Hz.
+static uint32_t timer_frequency;
+#if SL_SLEEPTIMER_WALLCLOCK_CONFIG
+// Current time count.
+static sl_sleeptimer_timestamp_t second_count;
+// Tick rest when the frequency is not a divider of the timer width.
+static uint32_t overflow_tick_rest = 0;
+#endif
+
+/*******************************************************************************
+ * Checks if the time stamp, format and time zone are
+ * within the supported range.
+ *
+ * @param time Time stamp to check.
+ * @param format Format of the time.
+ * @param time_zone Time zone offset in second.
+ *
+ * @return true if the time is valid. False otherwise.
+ ******************************************************************************/
+static bool is_valid_time(sl_sleeptimer_timestamp_t time, sl_sleeptimer_time_format_t format,
+ sl_sleeptimer_time_zone_offset_t time_zone)
+{
+ bool valid_time = false;
+
+ // Check for overflow.
+ if ((time_zone < ZONE0 && time > (uint32_t) abs(time_zone)) || (time_zone >= ZONE0 && (time <= UINT32_MAX - time_zone)))
+ {
+ valid_time = true;
+ }
+ if (format == TIME_FORMAT_UNIX)
+ {
+ if (time > TIME_UNIX_TIMESTAMP_MAX)
+ { // Check if Unix time stamp is an
+ // unsigned 31 bits.
+ valid_time = false;
+ }
+ }
+ else
+ {
+ if ((format == TIME_FORMAT_NTP) && (time >= TIME_NTP_EPOCH_OFFSET_SEC))
+ {
+ valid_time &= true;
+ }
+ else if ((format == TIME_FORMAT_ZIGBEE_CLUSTER) && (time <= TIME_UNIX_TIMESTAMP_MAX - TIME_ZIGBEE_EPOCH_OFFSET_SEC))
+ {
+ valid_time &= true;
+ }
+ else
+ {
+ valid_time = false;
+ }
+ }
+ return valid_time;
+}
+
+/*******************************************************************************
+ * Gets RTCC timer frequency.
+ ******************************************************************************/
+uint32_t rsi_rtc_get_hal_timer_frequency(void)
+{
+ /* CMU_PrescToLog2 converts prescaler dividend to a logarithmic value. It only works for even
+ * numbers equal to 2^n.
+ * An unscaled dividend (dividend = argument + 1).
+ * So we need to send argument subtracted by 1
+ */
+ return (CMU_ClockFreqGet(cmuClock_RTCC) >> (CMU_PrescToLog2(SL_SLEEPTIMER_FREQ_DIVIDER - 1)));
+}
+
+/******************************************************************************
+ * Initializes RTCC sleep timer.
+ *****************************************************************************/
+void rsi_rtc_init_timer(void)
+{
+ RTCC_Init_TypeDef rtcc_init = RTCC_INIT_DEFAULT;
+ RTCC_CCChConf_TypeDef channel = RTCC_CH_INIT_COMPARE_DEFAULT;
+
+ CMU_ClockEnable(cmuClock_RTCC, true);
+
+ rtcc_init.enable = false;
+
+ /* CMU_PrescToLog2 converts prescaler dividend to a logarithmic value. It only works for even
+ * numbers equal to 2^n.
+ * An unscaled dividend (dividend = argument + 1).
+ * So we need to send argument subtracted by 1
+ */
+ rtcc_init.presc = (RTCC_CntPresc_TypeDef)(CMU_PrescToLog2(SL_SLEEPTIMER_FREQ_DIVIDER - 1));
+
+ RTCC_Init(&rtcc_init);
+
+ // Compare channel starts disabled and is enabled only when compare match
+ // interrupt is enabled.
+ channel.chMode = rtccCapComChModeOff;
+ RTCC_ChannelInit(CH_SELECTOR, &channel);
+
+ RTCC_IntDisable(_RTCC_IEN_MASK);
+ RTCC_IntClear(_RTCC_IF_MASK);
+ RTCC_CounterSet(RTC_DEFAULT_COUNTER_VALUE);
+
+ RTCC_Enable(true);
+
+ NVIC_ClearPendingIRQ(RTCC_IRQn);
+ NVIC_EnableIRQ(RTCC_IRQn);
+}
+
+/******************************************************************************
+ * Enables RTCC interrupts.
+ *****************************************************************************/
+void rsi_rtc_enable_int(uint8_t local_flag)
+{
+ uint32_t rtcc_ien = 0u;
+
+ if (local_flag & SLEEPTIMER_EVENT_OF)
+ {
+ rtcc_ien |= RTCC_IEN_OF;
+ }
+
+ if (local_flag & SLEEPTIMER_EVENT_COMP)
+ {
+ rtcc_ien |= RTCC_IEN_CC1;
+ }
+
+ RTCC_IntEnable(rtcc_ien);
+}
+
+/*******************************************************************************
+ * Get timer frequency.
+ ******************************************************************************/
+uint32_t rsi_rtc_get_timer_frequency(void)
+{
+ return timer_frequency;
+}
+
+/******************************************************************************
+ * Gets RTCC counter value.
+ *****************************************************************************/
+uint32_t rsi_rtc_get_counter(void)
+{
+ return RTCC_CounterGet();
+}
+
+sl_status_t rsi_rtc_init(void)
+{
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+
+ if (!is_sleeptimer_initialized)
+ {
+ rsi_rtc_init_timer();
+ rsi_rtc_enable_int(SLEEPTIMER_EVENT_OF);
+ timer_frequency = rsi_rtc_get_hal_timer_frequency();
+ if (timer_frequency == RSI_RTC_FREQ_VALUE)
+ {
+ CORE_EXIT_ATOMIC();
+ return SL_STATUS_INVALID_PARAMETER;
+ }
+
+#if SL_SLEEPTIMER_WALLCLOCK_CONFIG
+ second_count = 0;
+#endif
+
+ is_sleeptimer_initialized = true;
+ }
+ CORE_EXIT_ATOMIC();
+
+ return SL_STATUS_OK;
+}
+
+#if SL_SLEEPTIMER_WALLCLOCK_CONFIG
+/*******************************************************************************
+ * Retrieves current time.
+ ******************************************************************************/
+uint32_t rsi_rtc_get_time(void)
+{
+ uint32_t cnt = 0u;
+ uint32_t freq = 0u;
+ sl_sleeptimer_timestamp_t time;
+ CORE_DECLARE_IRQ_STATE;
+
+ cnt = rsi_rtc_get_counter();
+ freq = rsi_rtc_get_timer_frequency();
+
+ CORE_ENTER_ATOMIC();
+ time = second_count + cnt / freq;
+ if (cnt % freq + overflow_tick_rest >= freq)
+ {
+ time++;
+ }
+ CORE_EXIT_ATOMIC();
+
+ return time;
+}
+
+/*******************************************************************************
+ * Sets current time.
+ ******************************************************************************/
+sl_status_t rsi_rtc_settime(sl_sleeptimer_timestamp_t time)
+{
+ uint32_t freq = 0u;
+ uint32_t counter_sec = 0u;
+ uint32_t cnt = 0;
+ CORE_DECLARE_IRQ_STATE;
+
+ if (!is_valid_time(time, TIME_FORMAT_UNIX, TIME_ZONE_OFFSET))
+ {
+ return SL_STATUS_INVALID_CONFIGURATION;
+ }
+
+ freq = rsi_rtc_get_timer_frequency();
+ cnt = rsi_rtc_get_counter();
+
+ CORE_ENTER_ATOMIC();
+ second_count = time;
+ overflow_tick_rest = 0;
+ counter_sec = cnt / freq;
+
+ if (second_count >= counter_sec)
+ {
+ second_count -= counter_sec;
+ }
+ else
+ {
+ CORE_EXIT_ATOMIC();
+ return SL_STATUS_INVALID_CONFIGURATION;
+ }
+
+ CORE_EXIT_ATOMIC();
+
+ return SL_STATUS_OK;
+}
+
+/*******************************************************************************
+ * @fn int32_t rsi_rtc_set_time(uint32_t time)
+ * @brief
+ * Init Sleeptimer and Set current time.
+ * @param[in] time:
+ * @return
+ * None
+ ******************************************************************************/
+int32_t rsi_rtc_set_time(uint32_t time)
+{
+ sl_status_t ret_val = SL_STATUS_OK;
+ ret_val = rsi_rtc_init();
+ if (ret_val != SL_STATUS_OK)
+ {
+ return -1;
+ }
+ else
+ {
+ ret_val = rsi_rtc_settime(time);
+ if (ret_val != SL_STATUS_OK)
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
+#endif // SL_SLEEPTIMER_WALLCLOCK_CONFIG
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_timer.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_timer.c
new file mode 100644
index 0000000..c6d6381
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_timer.c
@@ -0,0 +1,322 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Includes
+ */
+
+#include "em_cmu.h"
+#ifdef RSI_WITH_OS
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+#include "timers.h"
+#if defined(SysTick)
+#undef SysTick_Handler
+/* FreeRTOS SysTick interrupt handler prototype */
+extern void SysTick_Handler(void);
+/* FreeRTOS tick timer interrupt handler prototype */
+extern void xPortSysTickHandler(void);
+#endif /* SysTick */
+#endif /* RSI_WITH_OS */
+#include "wfx_host_events.h"
+
+/* RSI Driver include file */
+#include "rsi_driver.h"
+/* RSI WLAN Config include file */
+#include "rsi_bootup_config.h"
+#include "rsi_common_apis.h"
+#include "rsi_data_types.h"
+#include "rsi_error.h"
+#include "rsi_nwk.h"
+#include "rsi_socket.h"
+#include "rsi_utils.h"
+#include "rsi_wlan.h"
+#include "rsi_wlan_apis.h"
+#include "rsi_wlan_config.h"
+#include "wfx_rsi.h"
+
+#ifndef _use_the_rsi_defined_functions
+
+StaticTimer_t sRsiTimerBuffer;
+
+/*
+ * We (Matter port) need a few functions out of this file
+ * They are at the top
+ */
+uint32_t rsi_hal_gettickcount(void)
+{
+ return xTaskGetTickCount();
+}
+void rsi_delay_ms(uint32_t delay_ms)
+{
+#ifndef RSI_WITH_OS
+ uint32_t start;
+#endif
+ if (delay_ms == 0) // Check if delay is 0msec
+ return;
+
+#ifdef RSI_WITH_OS
+ vTaskDelay(pdMS_TO_TICKS(delay_ms));
+#else
+ start = rsi_hal_gettickcount();
+ do
+ {
+ } while (rsi_hal_gettickcount() - start < delay_ms);
+#endif
+}
+static struct rsi_timer
+{
+ void (*func)(void);
+ TimerHandle_t handle;
+ uint8_t id;
+ uint8_t name[3];
+} rsi_timer[WFX_RSI_NUM_TIMERS];
+static void timer_cb(TimerHandle_t thandle)
+{
+ int x;
+ for (x = 0; x < WFX_RSI_NUM_TIMERS; x++)
+ {
+ if (rsi_timer[x].handle == thandle)
+ {
+ (*rsi_timer[x].func)();
+ break;
+ }
+ }
+}
+
+/*
+ * Run a one-shot/periodic timer
+ */
+int32_t rsi_timer_start(uint8_t timer_node, uint8_t mode, uint8_t type, uint32_t duration, void (*rsi_timer_cb)(void))
+{
+ int x;
+ struct rsi_timer * tp;
+
+ if (mode == RSI_HAL_TIMER_MODE_MILLI)
+ return RSI_ERROR_INVALID_OPTION; /* Not supported for now - Fix this later */
+ for (x = 0; x < WFX_RSI_NUM_TIMERS; x++)
+ {
+ tp = &rsi_timer[x];
+ if (tp->handle == NULL)
+ {
+ goto found;
+ }
+ }
+ /* No space */
+ return RSI_ERROR_INSUFFICIENT_BUFFER;
+found:
+ tp->name[0] = 'r';
+ tp->name[1] = timer_node;
+ tp->name[2] = 0;
+ tp->func = rsi_timer_cb;
+ tp->handle =
+ xTimerCreateStatic((char *) &tp->name[0], pdMS_TO_TICKS(duration),
+ ((mode == RSI_HAL_TIMER_TYPE_SINGLE_SHOT) ? pdFALSE : pdTRUE), NULL, timer_cb, &sRsiTimerBuffer);
+
+ if (tp->handle == NULL)
+ {
+ return RSI_ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ (void) xTimerStart(tp->handle, TIMER_TICKS_TO_WAIT_0);
+
+ return RSI_ERROR_NONE;
+}
+#else /* _use_the_rsi_defined_functions */
+
+/* Counts 1ms timeTicks */
+volatile uint32_t msTicks = 0;
+
+/*===================================================*/
+/**
+ * @fn int32_t rsi_timer_start(uint8_t timer_no, uint8_t mode,uint8_t type,uint32_t duration,void (*
+ * rsi_timer_expiry_handler)())
+ * @brief Starts and configures timer
+ * @param[in] timer_node, timer node to be configured.
+ * @param[in] mode , mode of the timer
+ * 0 - Micro seconds mode
+ * 1 - Milli seconds mode
+ * @param[in] type, type of the timer
+ * 0 - single shot type
+ * 1 - periodic type
+ * @param[in] duration, timer duration
+ * @param[in] rsi_timer_expiry_handler() ,call back function to handle timer interrupt
+ * @param[out] none
+ * @return 0 - success
+ * !0 - Failure
+ * @description This HAL API should contain the code to initialize the timer and start the timer
+ *
+ */
+
+int32_t rsi_timer_start(uint8_t timer_node, uint8_t mode, uint8_t type, uint32_t duration, void (*rsi_timer_expiry_handler)(void))
+{
+
+ // Initialise the timer
+
+ // register the call back
+
+ // Start timer
+
+ return 0;
+}
+
+/*===================================================*/
+/**
+ * @fn int32_t rsi_timer_stop(uint8_t timer_no)
+ * @brief Stops timer
+ * @param[in] timer_node, timer node to stop
+ * @param[out] none
+ * @return 0 - success
+ * !0 - Failure
+ * @description This HAL API should contain the code to stop the timer
+ *
+ */
+
+int32_t rsi_timer_stop(uint8_t timer_node)
+{
+
+ // Stop the timer
+
+ return 0;
+}
+
+/*===================================================*/
+/**
+ * @fn uint32_t rsi_timer_read(uint8_t timer_node)
+ * @brief read timer
+ * @param[in] timer_node, timer node to read
+ * @param[out] none
+ * @return timer value
+ * @description This HAL API should contain API to read the timer
+ *
+ */
+uint32_t rsi_timer_read(uint8_t timer_node)
+{
+
+ volatile uint32_t timer_val = 0;
+
+ // read the timer and return timer value
+
+ return timer_val;
+}
+
+/*===================================================*/
+/**
+ * @fn void rsi_delay_us(uint32_t delay)
+ * @brief create delay in micro seconds
+ * @param[in] delay_us, timer delay in micro seconds
+ * @param[out] none
+ * @return none
+ * @description This HAL API should contain the code to create delay in micro seconds
+ *
+ */
+void rsi_delay_us(uint32_t delay_us)
+{
+
+ // call the API for delay in micro seconds
+
+ return;
+}
+
+#ifdef RSI_M4_INTERFACE
+
+extern void SysTick_Handler(void);
+
+void SysTick_Handler(void)
+{
+ _dwTickCount++;
+}
+
+uint32_t GetTickCount(void)
+{
+ return _dwTickCount; // gets the tick count from systic ISR
+}
+#endif
+
+/*===================================================*/
+/**
+ * @fn void rsi_delay_ms(uint32_t delay)
+ * @brief create delay in milli seconds
+ * @param[in] delay, timer delay in milli seconds
+ * @param[out] none
+ * @return none
+ * @description This HAL API should contain the code to create delay in milli seconds
+ */
+void rsi_delay_ms(uint32_t delay_ms)
+{
+#ifndef RSI_WITH_OS
+ uint32_t start;
+#endif
+ if (delay_ms == DELAY0)
+ return;
+
+#ifdef RSI_WITH_OS
+ vTaskDelay(delay_ms);
+#else
+ start = rsi_hal_gettickcount();
+ do
+ {
+ } while (rsi_hal_gettickcount() - start < delay_ms);
+#endif
+}
+
+/*===================================================*/
+/**
+ * @fn uint32_t rsi_hal_gettickcount()
+ * @brief provides a tick value in milliseconds
+ * @return tick value
+ * @description This HAL API should contain the code to read the timer tick count value in milliseconds
+ *
+ */
+
+#ifndef RSI_HAL_USE_RTOS_SYSTICK
+/*
+ SysTick handler implementation that also clears overflow flag.
+*/
+void SysTick_Handler(void)
+{
+ /* Increment counter necessary in Delay()*/
+ msTicks++;
+#ifdef RSI_WITH_OS
+ if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
+ {
+ xPortSysTickHandler();
+ }
+#endif
+}
+
+uint32_t rsi_hal_gettickcount(void)
+{
+ return msTicks;
+
+#ifdef LINUX_PLATFORM
+ // Define your API to get the tick count delay in milli seconds from systic ISR and return the resultant value
+ struct rsi_timeval tv1;
+ gettimeofday(&tv1, NULL);
+ return (tv1.tv_sec * CONVERT_SEC_TO_MSEC + tv1.tv_usec * CONVERT_USEC_TO_MSEC);
+#endif
+}
+
+#else
+uint32_t rsi_hal_gettickcount(void)
+{
+ return xTaskGetTickCount();
+}
+#endif /* RSI_HAL_USE_RTOS_SYSTICK */
+#endif /* _use_the_rsi_defined_functions */
diff --git a/examples/platform/silabs/SiWx917/rs911x/rs911x.gni b/examples/platform/silabs/SiWx917/rs911x/rs911x.gni
new file mode 100644
index 0000000..f119810
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/rs911x.gni
@@ -0,0 +1,101 @@
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+wifi_sdk_dir = "${chip_root}/src/platform/silabs/EFR32/wifi"
+wiseconnect_sdk_root = "${chip_root}/third_party/silabs/wiseconnect-wifi-bt-sdk"
+rs911x_cflags = []
+
+rs911x_src_plat = [
+ "${examples_plat_dir}/rs911x/rsi_if.c",
+ "${examples_plat_dir}/rs911x/wfx_rsi_host.c",
+ "${wifi_sdk_dir}/wfx_notify.cpp",
+ "${examples_plat_dir}/rs911x/hal/rsi_hal_mcu_interrupt.c",
+ "${examples_plat_dir}/rs911x/hal/rsi_hal_mcu_ioports.c",
+ "${examples_plat_dir}/rs911x/hal/rsi_hal_mcu_timer.c",
+ "${examples_plat_dir}/rs911x/hal/efx_spi.c",
+]
+rs911x_plat_incs = [
+ "${wifi_sdk_dir}",
+ "${wifi_sdk_dir}/hal",
+ "${chip_root}/src/platform/EFR32",
+]
+
+#
+# All the stuff from wiseconnect
+#
+rs911x_src_sapi = [
+ "${wiseconnect_sdk_root}/sapi/wlan/rsi_wlan_apis.c",
+ "${wiseconnect_sdk_root}/sapi/common/rsi_apis_non_rom.c",
+ "${wiseconnect_sdk_root}/sapi/common/rsi_apis_rom.c",
+ "${wiseconnect_sdk_root}/sapi/common/rsi_common_apis.c",
+ "${wiseconnect_sdk_root}/sapi/common/rsi_device_init_apis.c",
+ "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_frame_rd_wr.c",
+ "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_functs.c",
+ "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_iface_init.c",
+ "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_mem_rd_wr.c",
+ "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_reg_rd_wr.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_common.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_device_init.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_driver_event_handlers.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_driver.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_events_rom.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_events.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_iap.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_nwk_rom.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_nwk.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_pkt_mgmt_rom.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_pkt_mgmt.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_queue_rom.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_queue.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_scheduler_rom.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_scheduler.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_setregion_countryinfo.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_timer.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_utils_rom.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_utils.c",
+ "${wiseconnect_sdk_root}/sapi/driver/rsi_wlan.c",
+ "${wiseconnect_sdk_root}/sapi/rtos/freertos_wrapper/rsi_os_wrapper.c",
+]
+
+foreach(src_file, rs911x_src_sapi) {
+ rs911x_cflags += [ "-Wno-empty-body" ]
+}
+
+rs911x_inc_plat = [
+ "${wifi_sdk_dir}",
+ "${examples_plat_dir}/rs911x",
+ "${examples_plat_dir}/rs911x/hal",
+ "${wiseconnect_sdk_root}/sapi/include",
+]
+
+# Apparently - the rsi library needs this
+rs911x_src_sock = [
+ "${wiseconnect_sdk_root}/sapi/network/socket/rsi_socket.c",
+ "${wiseconnect_sdk_root}/sapi/network/socket/rsi_socket_rom.c",
+]
+rs911x_sock_inc = [ "${wifi_sdk_dir}/rsi-sockets" ]
+
+#
+# If we use LWIP - not built-in sockets
+#
+rs911x_src_lwip = [
+ "${wifi_sdk_dir}/ethernetif.cpp",
+ "${wifi_sdk_dir}/dhcp_client.cpp",
+ "${wifi_sdk_dir}/lwip_netif.cpp",
+]
+rs911x_defs = [
+ "SL_HEAP_SIZE=32768",
+ "SL_WIFI=1",
+ "SL_WFX_USE_SPI",
+ "EFX32_RS911X=1",
+ "RS911X_WIFI",
+ "RSI_WLAN_ENABLE",
+ "RSI_SPI_INTERFACE",
+ "RSI_WITH_OS",
+]
+rs911x_sock_defs = [
+ "RS911X_SOCKETS",
+ "RSI_IPV6_ENABLE",
+]
diff --git a/examples/platform/silabs/SiWx917/rs911x/rsi_if.c b/examples/platform/silabs/SiWx917/rs911x/rsi_if.c
new file mode 100644
index 0000000..7d3be40
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/rsi_if.c
@@ -0,0 +1,854 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+
+#include "rsi_driver.h"
+#include "rsi_wlan_non_rom.h"
+
+#include "rsi_common_apis.h"
+#include "rsi_data_types.h"
+#include "rsi_nwk.h"
+#include "rsi_socket.h"
+#include "rsi_utils.h"
+#include "rsi_wlan.h"
+#include "rsi_wlan_apis.h"
+#include "rsi_wlan_config.h"
+//#include "rsi_wlan_non_rom.h"
+#include "rsi_bootup_config.h"
+#include "rsi_error.h"
+
+#include "dhcp_client.h"
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+/* Rsi driver Task will use as its stack */
+StackType_t driverRsiTaskStack[WFX_RSI_WLAN_TASK_SZ] = { 0 };
+
+/* Structure that will hold the TCB of the wfxRsi Task being created. */
+StaticTask_t driverRsiTaskBuffer;
+
+/* Declare a variable to hold the data associated with the created event group. */
+StaticEventGroup_t rsiDriverEventGroup;
+
+bool hasNotifiedIPV6 = false;
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+bool hasNotifiedIPV4 = false;
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+bool hasNotifiedWifiConnectivity = false;
+
+/*
+ * This file implements the interface to the RSI SAPIs
+ */
+static uint8_t wfx_rsi_drv_buf[WFX_RSI_BUF_SZ];
+wfx_wifi_scan_ext_t * temp_reset;
+uint8_t security;
+
+/******************************************************************
+ * @fn int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t *ap)
+ * @brief
+ * Getting the AP details
+ * @param[in] ap: access point
+ * @return
+ * status
+ *********************************************************************/
+int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap)
+{
+ int32_t status;
+ uint8_t rssi;
+ ap->security = security;
+ ap->chan = wfx_rsi.ap_chan;
+ memcpy(&ap->bssid[0], &wfx_rsi.ap_mac.octet[0], BSSID_MAX_STR_LEN);
+ status = rsi_wlan_get(RSI_RSSI, &rssi, sizeof(rssi));
+ if (status == RSI_SUCCESS)
+ {
+ ap->rssi = (-1) * rssi;
+ }
+ return status;
+}
+
+/******************************************************************
+ * @fn int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t *extra_info)
+ * @brief
+ * Getting the AP extra details
+ * @param[in] extra info: access point extra information
+ * @return
+ * status
+ *********************************************************************/
+int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info)
+{
+ int32_t status;
+ uint8_t buff[RSI_RESPONSE_MAX_SIZE] = { 0 };
+ status = rsi_wlan_get(RSI_WLAN_EXT_STATS, buff, sizeof(buff));
+ if (status != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("\r\n Failed, Error Code : 0x%lX\r\n", status);
+ }
+ else
+ {
+ rsi_wlan_ext_stats_t * test = (rsi_wlan_ext_stats_t *) buff;
+ extra_info->beacon_lost_count = test->beacon_lost_count - temp_reset->beacon_lost_count;
+ extra_info->beacon_rx_count = test->beacon_rx_count - temp_reset->beacon_rx_count;
+ extra_info->mcast_rx_count = test->mcast_rx_count - temp_reset->mcast_rx_count;
+ extra_info->mcast_tx_count = test->mcast_tx_count - temp_reset->mcast_tx_count;
+ extra_info->ucast_rx_count = test->ucast_rx_count - temp_reset->ucast_rx_count;
+ extra_info->ucast_tx_count = test->ucast_tx_count - temp_reset->ucast_tx_count;
+ extra_info->overrun_count = test->overrun_count - temp_reset->overrun_count;
+ }
+ return status;
+}
+
+/******************************************************************
+ * @fn int32_t wfx_rsi_reset_count()
+ * @brief
+ * Getting the driver reset count
+ * @param[in] None
+ * @return
+ * status
+ *********************************************************************/
+int32_t wfx_rsi_reset_count()
+{
+ int32_t status;
+ uint8_t buff[RSI_RESPONSE_MAX_SIZE] = { 0 };
+ status = rsi_wlan_get(RSI_WLAN_EXT_STATS, buff, sizeof(buff));
+ if (status != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("\r\n Failed, Error Code : 0x%lX\r\n", status);
+ }
+ else
+ {
+ rsi_wlan_ext_stats_t * test = (rsi_wlan_ext_stats_t *) buff;
+ temp_reset->beacon_lost_count = test->beacon_lost_count;
+ temp_reset->beacon_rx_count = test->beacon_rx_count;
+ temp_reset->mcast_rx_count = test->mcast_rx_count;
+ temp_reset->mcast_tx_count = test->mcast_tx_count;
+ temp_reset->ucast_rx_count = test->ucast_rx_count;
+ temp_reset->ucast_tx_count = test->ucast_tx_count;
+ temp_reset->overrun_count = test->overrun_count;
+ }
+ return status;
+}
+
+/******************************************************************
+ * @fn wfx_rsi_disconnect()
+ * @brief
+ * Getting the driver disconnect status
+ * @param[in] None
+ * @return
+ * status
+ *********************************************************************/
+int32_t wfx_rsi_disconnect()
+{
+ int32_t status = rsi_wlan_disconnect();
+ return status;
+}
+
+/******************************************************************
+ * @fn wfx_rsi_join_cb(uint16_t status, const uint8_t *buf, const uint16_t len)
+ * @brief
+ * called when driver join with cb
+ * @param[in] status:
+ * @param[in] buf:
+ * @param[in] len:
+ * @return
+ * None
+ *********************************************************************/
+static void wfx_rsi_join_cb(uint16_t status, const uint8_t * buf, const uint16_t len)
+{
+ WFX_RSI_LOG("%s: status: %02x", __func__, status);
+ wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTING;
+ temp_reset = (wfx_wifi_scan_ext_t *) malloc(sizeof(wfx_wifi_scan_ext_t));
+ memset(temp_reset, 0, sizeof(wfx_wifi_scan_ext_t));
+ if (status != RSI_SUCCESS)
+ {
+ /*
+ * We should enable retry.. (Need config variable for this)
+ */
+ WFX_RSI_LOG("%s: failed. retry: %d", __func__, wfx_rsi.join_retries);
+#if (WFX_RSI_CONFIG_MAX_JOIN != 0)
+ if (++wfx_rsi.join_retries < WFX_RSI_CONFIG_MAX_JOIN)
+#endif
+ {
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN);
+ }
+ }
+ else
+ {
+ /*
+ * Join was complete - Do the DHCP
+ */
+ WFX_RSI_LOG("%s: join completed.", __func__);
+#ifdef RS911X_SOCKETS
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_DO_DHCP);
+#else
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_CONN);
+#endif
+ }
+}
+
+/******************************************************************
+ * @fn wfx_rsi_join_fail_cb(uint16_t status, uint8_t *buf, uint32_t len)
+ * @brief
+ * called when driver fail to join with cb
+ * @param[in] status:
+ * @param[in] buf:
+ * @param[in] len:
+ * @return
+ * None
+ *********************************************************************/
+static void wfx_rsi_join_fail_cb(uint16_t status, uint8_t * buf, uint32_t len)
+{
+ WFX_RSI_LOG("%s: error: failed status: %02x on try %d", __func__, status, wfx_rsi.join_retries);
+ wfx_rsi.join_retries += 1;
+ wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTING;
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN);
+}
+#ifdef RS911X_SOCKETS
+
+/******************************************************************
+ * @fn wfx_rsi_ipchange_cb(uint16_t status, uint8_t *buf, uint32_t len)
+ * @brief
+ * DHCP should end up here
+ * @param[in] status:
+ * @param[in] buf:
+ * @param[in] len:
+ * @return
+ * None
+ *********************************************************************/
+static void wfx_rsi_ipchange_cb(uint16_t status, uint8_t * buf, uint32_t len)
+{
+ WFX_RSI_LOG("%s: status: %02x", __func__, status);
+ if (status != RSI_SUCCESS)
+ {
+ /* Restart DHCP? */
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_DO_DHCP);
+ }
+ else
+ {
+ wfx_rsi.dev_state |= WFX_RSI_ST_STA_DHCP_DONE;
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_DHCP_DONE);
+ }
+}
+
+#else
+/*************************************************************************************
+ * @fn wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t *buf, uint32_t len)
+ * @brief
+ * Got RAW WLAN data pkt
+ * @param[in] status:
+ * @param[in] buf:
+ * @param[in] len:
+ * @return
+ * None
+ *****************************************************************************************/
+static void wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t * buf, uint32_t len)
+{
+ // WFX_RSI_LOG("%s: status=%d, len=%d", __func__, status, len);
+ if (status != RSI_SUCCESS)
+ {
+ return;
+ }
+ wfx_host_received_sta_frame_cb(buf, len);
+}
+#endif /* !Socket support */
+
+/*************************************************************************************
+ * @fn static int32_t wfx_rsi_init(void)
+ * @brief
+ * driver initialization
+ * @param[in] None
+ * @return
+ * None
+ *****************************************************************************************/
+static int32_t wfx_rsi_init(void)
+{
+ int32_t status;
+ uint8_t buf[RSI_RESPONSE_HOLD_BUFF_SIZE];
+ extern void rsi_hal_board_init(void);
+
+ WFX_RSI_LOG("%s: starting(HEAP_SZ = %d)", __func__, SL_HEAP_SIZE);
+ //! Driver initialization
+ status = rsi_driver_init(wfx_rsi_drv_buf, WFX_RSI_BUF_SZ);
+ if ((status < RSI_DRIVER_STATUS) || (status > WFX_RSI_BUF_SZ))
+ {
+ WFX_RSI_LOG("%s: error: RSI drv init failed with status: %02x", __func__, status);
+ return status;
+ }
+
+ WFX_RSI_LOG("%s: rsi_device_init", __func__);
+ /* ! Redpine module intialisation */
+ if ((status = rsi_device_init(LOAD_NWP_FW)) != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: error: rsi_device_init failed with status: %02x", __func__, status);
+ return status;
+ }
+ WFX_RSI_LOG("%s: start wireless drv task", __func__);
+ /*
+ * Create the driver task
+ */
+ wfx_rsi.drv_task = xTaskCreateStatic((TaskFunction_t) rsi_wireless_driver_task, "rsi_drv", WFX_RSI_WLAN_TASK_SZ, NULL,
+ WLAN_TASK_PRIORITY, driverRsiTaskStack, &driverRsiTaskBuffer);
+ if (NULL == wfx_rsi.drv_task)
+ {
+ WFX_RSI_LOG("%s: error: rsi_wireless_driver_task failed", __func__);
+ return RSI_ERROR_INVALID_PARAM;
+ }
+
+ /* Initialize WiSeConnect or Module features. */
+ WFX_RSI_LOG("%s: rsi_wireless_init", __func__);
+ if ((status = rsi_wireless_init(OPER_MODE_0, COEX_MODE_0)) != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: error: rsi_wireless_init failed with status: %02x", __func__, status);
+ return status;
+ }
+
+ WFX_RSI_LOG("%s: get FW version..", __func__);
+ /*
+ * Get the MAC and other info to let the user know about it.
+ */
+ if (rsi_wlan_get(RSI_FW_VERSION, buf, sizeof(buf)) != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: error: rsi_wlan_get(RSI_FW_VERSION) failed with status: %02x", __func__, status);
+ return status;
+ }
+
+ buf[sizeof(buf) - 1] = 0;
+ WFX_RSI_LOG("%s: RSI firmware version: %s", __func__, buf);
+ //! Send feature frame
+ if ((status = rsi_send_feature_frame()) != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: error: rsi_send_feature_frame failed with status: %02x", __func__, status);
+ return status;
+ }
+
+ WFX_RSI_LOG("%s: sent rsi_send_feature_frame", __func__);
+ /* initializes wlan radio parameters and WLAN supplicant parameters.
+ */
+ (void) rsi_wlan_radio_init(); /* Required so we can get MAC address */
+ if ((status = rsi_wlan_get(RSI_MAC_ADDRESS, &wfx_rsi.sta_mac.octet[0], RESP_BUFF_SIZE)) != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: error: rsi_wlan_get failed with status: %02x", __func__, status);
+ return status;
+ }
+
+ WFX_RSI_LOG("%s: WLAN: MAC %02x:%02x:%02x %02x:%02x:%02x", __func__, wfx_rsi.sta_mac.octet[0], wfx_rsi.sta_mac.octet[1],
+ wfx_rsi.sta_mac.octet[2], wfx_rsi.sta_mac.octet[3], wfx_rsi.sta_mac.octet[4], wfx_rsi.sta_mac.octet[5]);
+ wfx_rsi.events = xEventGroupCreateStatic(&rsiDriverEventGroup);
+ /*
+ * Register callbacks - We are only interested in the connectivity CBs
+ */
+ if ((status = rsi_wlan_register_callbacks(RSI_JOIN_FAIL_CB, wfx_rsi_join_fail_cb)) != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: RSI callback register join failed with status: %02x", __func__, status);
+ return status;
+ }
+#ifdef RS911X_SOCKETS
+ (void) rsi_wlan_register_callbacks(RSI_IP_CHANGE_NOTIFY_CB, wfx_rsi_ipchange_cb);
+#else
+ if ((status = rsi_wlan_register_callbacks(RSI_WLAN_DATA_RECEIVE_NOTIFY_CB, wfx_rsi_wlan_pkt_cb)) != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: RSI callback register data-notify failed with status: %02x", __func__, status);
+ return status;
+ }
+#endif
+ wfx_rsi.dev_state |= WFX_RSI_ST_DEV_READY;
+ WFX_RSI_LOG("%s: RSI: OK", __func__);
+ return RSI_SUCCESS;
+}
+
+/*************************************************************************************
+ * @fn void wfx_show_err(char *msg)
+ * @brief
+ * driver shows error message
+ * @param[in] msg
+ * @return
+ * None
+ *****************************************************************************************/
+void wfx_show_err(char * msg)
+{
+ WFX_RSI_LOG("%s: message: %d", __func__, msg);
+}
+
+/***************************************************************************************
+ * @fn static void wfx_rsi_save_ap_info()
+ * @brief
+ * Saving the details of the AP
+ * @param[in] None
+ * @return
+ * None
+ *******************************************************************************************/
+static void wfx_rsi_save_ap_info()
+{
+ int32_t status;
+ rsi_rsp_scan_t rsp;
+
+ status =
+ rsi_wlan_scan_with_bitmap_options((int8_t *) &wfx_rsi.sec.ssid[0], AP_CHANNEL_NO_0, &rsp, sizeof(rsp), SCAN_BITMAP_OPTN_1);
+ if (status)
+ {
+ /*
+ * Scan is done - failed
+ */
+ }
+ else
+ {
+ wfx_rsi.sec.security = rsp.scan_info->security_mode;
+ wfx_rsi.ap_chan = rsp.scan_info->rf_channel;
+ memcpy(&wfx_rsi.ap_mac.octet[0], &rsp.scan_info->bssid[0], BSSID_MAX_STR_LEN);
+ }
+ if ((wfx_rsi.sec.security == RSI_WPA) || (wfx_rsi.sec.security == RSI_WPA2))
+ {
+ // saving the security before changing into mixed mode
+ security = wfx_rsi.sec.security;
+ wfx_rsi.sec.security = RSI_WPA_WPA2_MIXED;
+ }
+ if (wfx_rsi.sec.security == SME_WPA3)
+ {
+ // returning 3 for WPA3 when DGWIFI read security-type is called
+ security = WPA3_SECURITY;
+ wfx_rsi.sec.security = RSI_WPA3;
+ }
+ WFX_RSI_LOG("%s: WLAN: connecting to %s==%s, sec=%d, status=%02x", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0],
+ wfx_rsi.sec.security, status);
+}
+
+/********************************************************************************************
+ * @fn static void wfx_rsi_do_join(void)
+ * @brief
+ * Start an async Join command
+ * @return
+ * None
+ **********************************************************************************************/
+static void wfx_rsi_do_join(void)
+{
+ int32_t status;
+
+ if (wfx_rsi.dev_state & (WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED))
+ {
+ WFX_RSI_LOG("%s: not joining - already in progress", __func__);
+ }
+ else
+ {
+ WFX_RSI_LOG("%s: WLAN: connecting to %s==%s, sec=%d", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0],
+ wfx_rsi.sec.security);
+ /*
+ * Join the network
+ */
+ /* TODO - make the WFX_SECURITY_xxx - same as RSI_xxx
+ * Right now it's done by hand - we need something better
+ */
+ wfx_rsi.dev_state |= WFX_RSI_ST_STA_CONNECTING;
+
+ /* Try to connect Wifi with given Credentials
+ * until there is a success or maximum number of tries allowed
+ */
+ while (++wfx_rsi.join_retries < WFX_RSI_CONFIG_MAX_JOIN)
+ {
+
+ /* Call rsi connect call with given ssid and password
+ * And check there is a success
+ */
+ if ((status = rsi_wlan_connect_async((int8_t *) &wfx_rsi.sec.ssid[0], (rsi_security_mode_t) wfx_rsi.sec.security,
+ &wfx_rsi.sec.passkey[0], wfx_rsi_join_cb)) != RSI_SUCCESS)
+ {
+
+ wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTING;
+ WFX_RSI_LOG("%s: rsi_wlan_connect_async failed with status: %02x on try %d", __func__, status,
+ wfx_rsi.join_retries);
+ vTaskDelay(4000);
+ /* TODO - Start a timer.. to retry */
+ }
+ else
+ {
+ break; // exit while loop
+ }
+ }
+ if (wfx_rsi.join_retries == MAX_JOIN_RETRIES_COUNT)
+ {
+ WFX_RSI_LOG("Connect failed after %d tries", wfx_rsi.join_retries);
+ }
+ else
+ {
+ WFX_RSI_LOG("%s: starting JOIN to %s after %d tries\n", __func__, (char *) &wfx_rsi.sec.ssid[0], wfx_rsi.join_retries);
+ }
+ }
+}
+
+/*********************************************************************************
+ * @fn void wfx_rsi_task(void *arg)
+ * @brief
+ * The main WLAN task - started by wfx_wifi_start () that interfaces with RSI.
+ * The rest of RSI stuff come in call-backs.
+ * The initialization has been already done.
+ * @param[in] arg:
+ * @return
+ * None
+ **********************************************************************************/
+/* ARGSUSED */
+void wfx_rsi_task(void * arg)
+{
+ EventBits_t flags;
+#ifndef RS911X_SOCKETS
+ TickType_t last_dhcp_poll, now;
+ struct netif * sta_netif;
+#endif
+ (void) arg;
+ uint32_t rsi_status = wfx_rsi_init();
+ if (rsi_status != RSI_SUCCESS)
+ {
+ WFX_RSI_LOG("%s: error: wfx_rsi_init with status: %02x", __func__, rsi_status);
+ return;
+ }
+#ifndef RS911X_SOCKETS
+ wfx_lwip_start();
+ last_dhcp_poll = xTaskGetTickCount();
+ sta_netif = wfx_get_netif(SL_WFX_STA_INTERFACE);
+#endif
+ wfx_started_notify();
+
+ WFX_RSI_LOG("%s: starting event wait", __func__);
+ for (;;)
+ {
+ /*
+ * This is the main job of this task.
+ * Wait for commands from the ConnectivityManager
+ * Make state changes (based on call backs)
+ */
+ flags = xEventGroupWaitBits(wfx_rsi.events,
+ WFX_EVT_STA_CONN | WFX_EVT_STA_DISCONN | WFX_EVT_STA_START_JOIN
+#ifdef RS911X_SOCKETS
+ | WFX_EVT_STA_DO_DHCP | WFX_EVT_STA_DHCP_DONE
+#endif /* RS911X_SOCKETS */
+#ifdef SL_WFX_CONFIG_SOFTAP
+ | WFX_EVT_AP_START | WFX_EVT_AP_STOP
+#endif /* SL_WFX_CONFIG_SOFTAP */
+#ifdef SL_WFX_CONFIG_SCAN
+ | WFX_EVT_SCAN
+#endif /* SL_WFX_CONFIG_SCAN */
+ | 0,
+ pdTRUE, /* Clear the bits */
+ pdFALSE, /* Wait for any bit */
+ pdMS_TO_TICKS(250)); /* 250 mSec */
+
+ if (flags)
+ {
+ WFX_RSI_LOG("%s: wait event encountered: %x", __func__, flags);
+ }
+#ifdef RS911X_SOCKETS
+ if (flags & WFX_EVT_STA_DO_DHCP)
+ {
+ /*
+ * Do DHCP -
+ */
+ if ((status = rsi_config_ipaddress(RSI_IP_VERSION_4, RSI_DHCP | RSI_DHCP_UNICAST_OFFER, NULL, NULL, NULL,
+ &wfx_rsi.ip4_addr[0], IP_CONF_RSP_BUFF_LENGTH_4, STATION)) != RSI_SUCCESS)
+ {
+ /* We should try this again.. (perhaps sleep) */
+ /* TODO - Figure out what to do here */
+ }
+ }
+#else /* !RS911X_SOCKET - using LWIP */
+ /*
+ * Let's handle DHCP polling here
+ */
+ if (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED)
+ {
+ if ((now = xTaskGetTickCount()) > (last_dhcp_poll + pdMS_TO_TICKS(250)))
+ {
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+ uint8_t dhcp_state = dhcpclient_poll(sta_netif);
+ if (dhcp_state == DHCP_ADDRESS_ASSIGNED && !hasNotifiedIPV4)
+ {
+ wfx_dhcp_got_ipv4((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr);
+ hasNotifiedIPV4 = true;
+ if (!hasNotifiedWifiConnectivity)
+ {
+ wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac);
+ hasNotifiedWifiConnectivity = true;
+ }
+ }
+ else if (dhcp_state == DHCP_OFF)
+ {
+ wfx_ip_changed_notify(IP_STATUS_FAIL);
+ hasNotifiedIPV4 = false;
+ }
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+ /* Checks if the assigned IPv6 address is preferred by evaluating
+ * the first block of IPv6 address ( block 0)
+ */
+ if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6)
+ {
+ wfx_ipv6_notify(GET_IPV6_SUCCESS);
+ hasNotifiedIPV6 = true;
+ if (!hasNotifiedWifiConnectivity)
+ {
+ wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac);
+ hasNotifiedWifiConnectivity = true;
+ }
+ }
+ last_dhcp_poll = now;
+ }
+ }
+#endif /* RS911X_SOCKETS */
+ if (flags & WFX_EVT_STA_START_JOIN)
+ {
+ // saving the AP related info
+ wfx_rsi_save_ap_info();
+ // Joining to the network
+ wfx_rsi_do_join();
+ }
+ if (flags & WFX_EVT_STA_CONN)
+ {
+ /*
+ * Initiate the Join command (assuming we have been provisioned)
+ */
+ WFX_RSI_LOG("%s: starting LwIP STA", __func__);
+ wfx_rsi.dev_state |= WFX_RSI_ST_STA_CONNECTED;
+#ifndef RS911X_SOCKETS
+ hasNotifiedWifiConnectivity = false;
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+ hasNotifiedIPV4 = false;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+ hasNotifiedIPV6 = false;
+ wfx_lwip_set_sta_link_up();
+#endif /* !RS911X_SOCKETS */
+ /* We need to get AP Mac - TODO */
+ // Uncomment once the hook into MATTER is moved to IP connectivity instead
+ // of AP connectivity. wfx_connected_notify(0, &wfx_rsi.ap_mac); // This
+ // is independent of IP connectivity.
+ }
+ if (flags & WFX_EVT_STA_DISCONN)
+ {
+ wfx_rsi.dev_state &=
+ ~(WFX_RSI_ST_STA_READY | WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED | WFX_RSI_ST_STA_DHCP_DONE);
+ WFX_RSI_LOG("%s: disconnect notify", __func__);
+ /* TODO: Implement disconnect notify */
+#ifndef RS911X_SOCKETS
+ wfx_lwip_set_sta_link_down(); // Internally dhcpclient_poll(netif) ->
+ // wfx_ip_changed_notify(0) for IPV4
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+ wfx_ip_changed_notify(IP_STATUS_FAIL);
+ hasNotifiedIPV4 = false;
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+ wfx_ipv6_notify(GET_IPV6_FAIL);
+ hasNotifiedIPV6 = false;
+ hasNotifiedWifiConnectivity = false;
+#endif /* !RS911X_SOCKETS */
+ }
+#ifdef SL_WFX_CONFIG_SCAN
+ if (flags & WFX_EVT_SCAN)
+ {
+ if (!(wfx_rsi.dev_state & WFX_RSI_ST_SCANSTARTED))
+ {
+ WFX_RSI_LOG("%s: start SSID scan", __func__);
+ int x;
+ wfx_wifi_scan_result_t ap;
+ rsi_scan_info_t * scan;
+ int32_t status;
+ uint8_t bgscan_results[BG_SCAN_RES_SIZE] = { 0 };
+ status = rsi_wlan_bgscan_profile(1, (rsi_rsp_scan_t *) bgscan_results, BG_SCAN_RES_SIZE);
+
+ WFX_RSI_LOG("%s: status: %02x size = %d", __func__, status, BG_SCAN_RES_SIZE);
+ rsi_rsp_scan_t * rsp = (rsi_rsp_scan_t *) bgscan_results;
+ if (status)
+ {
+ /*
+ * Scan is done - failed
+ */
+ }
+ else
+ for (x = 0; x < rsp->scan_count[0]; x++)
+ {
+ scan = &rsp->scan_info[x];
+ strcpy(&ap.ssid[0], (char *) &scan->ssid[0]);
+ if (wfx_rsi.scan_ssid)
+ {
+ WFX_RSI_LOG("Inside scan_ssid");
+ WFX_RSI_LOG("SCAN SSID: %s , ap scan: %s", wfx_rsi.scan_ssid, ap.ssid);
+ if (strcmp(wfx_rsi.scan_ssid, ap.ssid) == CMP_SUCCESS)
+ {
+ WFX_RSI_LOG("Inside ap details");
+ ap.security = scan->security_mode;
+ ap.rssi = (-1) * scan->rssi_val;
+ memcpy(&ap.bssid[0], &scan->bssid[0], BSSID_MAX_STR_LEN);
+ (*wfx_rsi.scan_cb)(&ap);
+ }
+ }
+ else
+ {
+ WFX_RSI_LOG("Inside else");
+ ap.security = scan->security_mode;
+ ap.rssi = (-1) * scan->rssi_val;
+ memcpy(&ap.bssid[0], &scan->bssid[0], BSSID_MAX_STR_LEN);
+ (*wfx_rsi.scan_cb)(&ap);
+ }
+ }
+ wfx_rsi.dev_state &= ~WFX_RSI_ST_SCANSTARTED;
+ /* Terminate with end of scan which is no ap sent back */
+ (*wfx_rsi.scan_cb)((wfx_wifi_scan_result_t *) 0);
+ wfx_rsi.scan_cb = (void (*)(wfx_wifi_scan_result_t *)) 0;
+
+ if (wfx_rsi.scan_ssid)
+ {
+ vPortFree(wfx_rsi.scan_ssid);
+ wfx_rsi.scan_ssid = (char *) 0;
+ }
+ }
+ }
+#endif /* SL_WFX_CONFIG_SCAN */
+#ifdef SL_WFX_CONFIG_SOFTAP
+ /* TODO */
+ if (flags & WFX_EVT_AP_START)
+ {
+ }
+ if (flags & WFX_EVT_AP_STOP)
+ {
+ }
+#endif /* SL_WFX_CONFIG_SOFTAP */
+ }
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+/********************************************************************************************
+ * @fn void wfx_dhcp_got_ipv4(uint32_t ip)
+ * @brief
+ * Acquire the new ip address
+ * @param[in] ip: internet protocol
+ * @return
+ * None
+ **********************************************************************************************/
+void wfx_dhcp_got_ipv4(uint32_t ip)
+{
+ /*
+ * Acquire the new IP address
+ */
+ wfx_rsi.ip4_addr[0] = (ip) &HEX_VALUE_FF;
+ wfx_rsi.ip4_addr[1] = (ip >> 8) & HEX_VALUE_FF;
+ wfx_rsi.ip4_addr[2] = (ip >> 16) & HEX_VALUE_FF;
+ wfx_rsi.ip4_addr[3] = (ip >> 24) & HEX_VALUE_FF;
+ WFX_RSI_LOG("%s: DHCP OK: IP=%d.%d.%d.%d", __func__, wfx_rsi.ip4_addr[0], wfx_rsi.ip4_addr[1], wfx_rsi.ip4_addr[2],
+ wfx_rsi.ip4_addr[3]);
+ /* Notify the Connectivity Manager - via the app */
+ wfx_ip_changed_notify(IP_STATUS_SUCCESS);
+ wfx_rsi.dev_state |= WFX_RSI_ST_STA_READY;
+}
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+
+/*
+ * WARNING - Taken from RSI and broken up
+ * This is my own RSI stuff for not copying code and allocating an extra
+ * level of indirection - when using LWIP buffers
+ * see also: int32_t rsi_wlan_send_data_xx(uint8_t *buffer, uint32_t length)
+ */
+/********************************************************************************************
+ * @fn void *wfx_rsi_alloc_pkt()
+ * @brief
+ * Allocate packet to send data
+ * @param[in] None
+ * @return
+ * None
+ **********************************************************************************************/
+void * wfx_rsi_alloc_pkt()
+{
+ rsi_pkt_t * pkt;
+
+ // Allocate packet to send data
+ if ((pkt = rsi_pkt_alloc(&rsi_driver_cb->wlan_cb->wlan_tx_pool)) == NULL)
+ {
+ return (void *) 0;
+ }
+
+ return (void *) pkt;
+}
+
+/********************************************************************************************
+ * @fn void wfx_rsi_pkt_add_data(void *p, uint8_t *buf, uint16_t len, uint16_t off)
+ * @brief
+ * add the data into packet
+ * @param[in] p:
+ * @param[in] buf:
+ * @param[in] len:
+ * @param[in] off:
+ * @return
+ * None
+ **********************************************************************************************/
+void wfx_rsi_pkt_add_data(void * p, uint8_t * buf, uint16_t len, uint16_t off)
+{
+ rsi_pkt_t * pkt;
+
+ pkt = (rsi_pkt_t *) p;
+ memcpy(((char *) pkt->data) + off, buf, len);
+}
+
+/********************************************************************************************
+ * @fn int32_t wfx_rsi_send_data(void *p, uint16_t len)
+ * @brief
+ * Driver send a data
+ * @param[in] p:
+ * @param[in] len:
+ * @return
+ * None
+ **********************************************************************************************/
+int32_t wfx_rsi_send_data(void * p, uint16_t len)
+{
+ int32_t status;
+ register uint8_t * host_desc;
+ rsi_pkt_t * pkt;
+
+ pkt = (rsi_pkt_t *) p;
+ host_desc = pkt->desc;
+ memset(host_desc, 0, RSI_HOST_DESC_LENGTH);
+ rsi_uint16_to_2bytes(host_desc, (len & 0xFFF));
+
+ // Fill packet type
+ host_desc[1] |= (RSI_WLAN_DATA_Q << 4);
+ host_desc[2] |= 0x01;
+
+ rsi_enqueue_pkt(&rsi_driver_cb->wlan_tx_q, pkt);
+
+#ifndef RSI_SEND_SEM_BITMAP
+ rsi_driver_cb_non_rom->send_wait_bitmap |= BIT(0);
+#endif
+ // Set TX packet pending event
+ rsi_set_event(RSI_TX_EVENT);
+
+ if (rsi_wait_on_wlan_semaphore(&rsi_driver_cb_non_rom->send_data_sem, RSI_SEND_DATA_RESPONSE_WAIT_TIME) != RSI_ERROR_NONE)
+ {
+ return RSI_ERROR_RESPONSE_TIMEOUT;
+ }
+ status = rsi_wlan_get_status();
+
+ return status;
+}
+
+struct wfx_rsi wfx_rsi;
diff --git a/examples/platform/silabs/SiWx917/rs911x/rsi_wlan_config.h b/examples/platform/silabs/SiWx917/rs911x/rsi_wlan_config.h
new file mode 100644
index 0000000..f2a47b5
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/rsi_wlan_config.h
@@ -0,0 +1,606 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSI_CONFIG_H
+#define RSI_CONFIG_H
+
+#include "rsi_wlan_defines.h"
+
+//! Enable feature
+#define RSI_ENABLE 1
+//! Disable feature
+#define RSI_DISABLE 0
+
+//! To enable wlan opermode
+#define RSI_OPERMODE_WLAN 0
+
+//! To enable concurrent mode
+#define CONCURRENT_MODE RSI_DISABLE
+
+//! opermode command parameters
+/*=======================================================================*/
+//! To set wlan feature select bit map
+#define RSI_FEATURE_BIT_MAP (FEAT_SECURITY_OPEN)
+
+//! TCP IP BYPASS feature check
+#ifdef RS911X_SOCKETS
+#define RSI_TCP_IP_BYPASS RSI_DISABLE
+
+#define RSI_TCP_IP_FEATURE_BIT_MAP \
+ (TCP_IP_FEAT_DHCPV4_CLIENT | /*TCP_IP_FEAT_HTTP_CLIENT | */ \
+ TCP_IP_FEAT_EXTENSION_VALID | /*TCP_IP_FEAT_SSL |*/ /*TCP_IP_FEAT_DNS_CLIENT |*/ \
+ 0)
+//! To set custom feature select bit map
+#define RSI_CUSTOM_FEATURE_BIT_MAP FEAT_CUSTOM_FEAT_EXTENSION_VALID
+
+#else /* Don't use RSI_SOCKETS */
+#define RSI_TCP_IP_BYPASS RSI_ENABLE
+#define RSI_TCP_IP_FEATURE_BIT_MAP (TCP_IP_FEAT_BYPASS /*| TCP_IP_FEAT_EXTENSION_VALID*/)
+#endif
+
+//! To set Extended custom feature select bit map
+#if WIFI_ENABLE_SECURITY_WPA3
+#ifdef RSI_M4_INTERFACE
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP (EXT_FEAT_256K_MODE | EXT_FEAT_IEEE_80211W)
+#else
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP (EXT_FEAT_384K_MODE | EXT_FEAT_IEEE_80211W)
+#endif
+#else
+#ifdef RSI_M4_INTERFACE
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP EXT_FEAT_256K_MODE
+#else
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP EXT_FEAT_384K_MODE
+#endif
+#endif
+
+//! To set Extended TCPIP feature select bit map
+#define RSI_EXT_TCPIP_FEATURE_BITMAP (/*EXT_FEAT_HTTP_OTAF_SUPPORT |*/ EXT_TCP_IP_SSL_16K_RECORD)
+//! Extended custom feature is selected internally
+//! CCP -- EXT_FEAT_256K_MODE
+//! Wiseconnect -- EXT_FEAT_384K_MODE
+/*=======================================================================*/
+//! Feature frame parameters
+/*=======================================================================*/
+#define PLL_MODE 0
+#define RF_TYPE 1 //! 0 - External RF 1- Internal RF
+#define WIRELESS_MODE 0
+#define ENABLE_PPP 0
+#define AFE_TYPE 1
+#define FEATURE_ENABLES 0
+/*=======================================================================*/
+//! Band command parameters
+/*=======================================================================*/
+
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_BAND RSI_BAND_2P4GHZ
+/*=======================================================================*/
+//! set region command parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Set region support
+#define RSI_SET_REGION_SUPPORT RSI_DISABLE //@ RSI_ENABLE or RSI_DISABLE set region
+
+//! If 1:region configurations taken from user ;0:region configurations taken from beacon
+#define RSI_SET_REGION_FROM_USER_OR_BEACON 1
+
+//! 0-Default Region domain ,1-US, 2-EUROPE, 3-JAPAN
+#define RSI_REGION_CODE 1
+
+//! 0- Without On Board Antenna , 1- With On Board Antenna
+#define RSI_MODULE_TYPE 1
+
+/*=======================================================================*/
+//! set region AP command parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Set region AP support
+#define RSI_SET_REGION_AP_SUPPORT RSI_DISABLE
+
+//! If 1:region configurations taken from user ;0:region configurations taken from firmware
+#define RSI_SET_REGION_AP_FROM_USER RSI_DISABLE
+
+//! "US" or "EU" or "JP" or other region codes
+#define RSI_COUNTRY_CODE "US"
+/*=======================================================================*/
+
+//! Rejoin parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE rejoin params
+#define RSI_REJOIN_PARAMS_SUPPORT RSI_ENABLE
+
+//! Rejoin retry count. If 0 retries infinity times
+#define RSI_REJOIN_MAX_RETRY 5
+
+//! Periodicity of rejoin attempt
+#define RSI_REJOIN_SCAN_INTERVAL 1
+
+//! Beacon missed count
+#define RSI_REJOIN_BEACON_MISSED_COUNT 40
+
+//! RSI_ENABLE or RSI_DISABLE retry for first time join failure
+#define RSI_REJOIN_FIRST_TIME_RETRY RSI_DISABLE
+
+/*=======================================================================*/
+
+//! BG scan command parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE BG Scan support
+#define RSI_BG_SCAN_SUPPORT RSI_ENABLE
+
+//! RSI_ENABLE or RSI_DISABLE BG scan
+#define RSI_BG_SCAN_ENABLE RSI_ENABLE
+
+//! RSI_ENABLE or RSI_DISABLE instant BG scan
+#define RSI_INSTANT_BG RSI_ENABLE
+
+//! BG scan threshold value
+#define RSI_BG_SCAN_THRESHOLD 63
+
+//! RSSI tolerance Threshold
+#define RSI_RSSI_TOLERANCE_THRESHOLD 4
+
+//! BG scan periodicity
+#define RSI_BG_SCAN_PERIODICITY 2
+
+//! Active scan duration
+#define RSI_ACTIVE_SCAN_DURATION 50
+
+//! Passive scan duration
+#define RSI_PASSIVE_SCAN_DURATION 50
+
+//! Multi probe
+#define RSI_MULTIPROBE RSI_ENABLE
+
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE to set RTS threshold config
+#define RSI_WLAN_CONFIG_ENABLE RSI_ENABLE
+
+#define CONFIG_RTSTHRESHOLD 1
+
+#define RSI_RTS_THRESHOLD 2346
+
+/*=======================================================================*/
+
+//! Roaming parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Roaming support
+#define RSI_ROAMING_SUPPORT RSI_DISABLE
+
+//! roaming threshold value
+#define RSI_ROAMING_THRESHOLD 67
+
+//! roaming hysterisis value
+#define RSI_ROAMING_HYSTERISIS 4
+
+/*=======================================================================*/
+//! High Throughput Capabilies related information
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE 11n mode in AP mode
+#define RSI_MODE_11N_ENABLE RSI_DISABLE
+
+//! HT caps supported
+#define RSI_HT_CAPS_NUM_RX_STBC (1 << 8)
+#define RSI_HT_CAPS_SHORT_GI_20MHZ BIT(5)
+#define RSI_HT_CAPS_GREENFIELD_EN BIT(4)
+#define RSI_HT_CAPS_SUPPORT_CH_WIDTH BIT(1)
+
+//! HT caps bit map.
+#define RSI_HT_CAPS_BIT_MAP \
+ (RSI_HT_CAPS_NUM_RX_STBC | RSI_HT_CAPS_SHORT_GI_20MHZ | RSI_HT_CAPS_GREENFIELD_EN | RSI_HT_CAPS_SUPPORT_CH_WIDTH)
+
+/*=======================================================================*/
+//! Scan command parameters
+/*=======================================================================*/
+
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_SCAN_CHANNEL_BIT_MAP_2_4 0
+
+//! scan channle bit map in 5GHz band ,valid if given channel to scan is 0
+#define RSI_SCAN_CHANNEL_BIT_MAP_5 0
+
+//! scan_feature_bitmap ,valid only if specific channel to scan and ssid are given
+#define RSI_SCAN_FEAT_BITMAP 0
+
+/*=======================================================================*/
+//! Enterprise configuration command parameters
+/*=======================================================================*/
+
+//! Enterprise method ,should be one of among TLS, TTLS, FAST or PEAP
+#define RSI_EAP_METHOD "TTLS"
+//! This parameter is used to configure the module in Enterprise security mode
+#define RSI_EAP_INNER_METHOD "\"auth=MSCHAPV2\""
+//! Private Key Password is required for encrypted private key, format is like "\"12345678\""
+#define RSI_PRIVATE_KEY_PASSWORD ""
+/*=======================================================================*/
+//! AP configuration command parameters
+/*=======================================================================*/
+
+//! This Macro is used to enable AP keep alive functionality
+#define RSI_AP_KEEP_ALIVE_ENABLE RSI_ENABLE
+
+//! This parameter is used to configure keep alive type
+#define RSI_AP_KEEP_ALIVE_TYPE RSI_NULL_BASED_KEEP_ALIVE
+
+//! This parameter is used to configure keep alive period
+#define RSI_AP_KEEP_ALIVE_PERIOD 100
+
+//! This parameter is used to configure maximum stations supported
+#define RSI_MAX_STATIONS_SUPPORT 4
+/*=======================================================================*/
+//! Join command parameters
+/*=======================================================================*/
+
+//! Tx power level
+#define RSI_POWER_LEVEL RSI_POWER_LEVEL_HIGH
+
+//! RSI_JOIN_FEAT_STA_BG_ONLY_MODE_ENABLE or RSI_JOIN_FEAT_LISTEN_INTERVAL_VALID
+#if WIFI_ENABLE_SECURITY_WPA3
+#define RSI_JOIN_FEAT_BIT_MAP RSI_JOIN_FEAT_MFP_CAPABLE_REQUIRED
+#else
+#define RSI_JOIN_FEAT_BIT_MAP 0
+#endif
+
+#define RSI_LISTEN_INTERVAL 0
+
+//! Transmission data rate. Physical rate at which data has to be transmitted.
+#define RSI_DATA_RATE RSI_DATA_RATE_AUTO
+
+/*=======================================================================*/
+//! Ipconf command parameters
+/*=======================================================================*/
+
+//! DHCP client host name
+#define RSI_DHCP_HOST_NAME "efr_9116"
+
+//! Transmit test command parameters
+/*=======================================================================*/
+//! TX TEST rate flags
+#define RSI_TX_TEST_RATE_FLAGS 0
+
+//! TX TEST per channel bandwidth
+#define RSI_TX_TEST_PER_CH_BW 0
+
+//! TX TEST aggregation enable or disable
+#define RSI_TX_TEST_AGGR_ENABLE RSI_DISABLE
+
+//! TX TEST delay
+#define RSI_TX_TEST_DELAY 0
+
+/*======================================================================*/
+//! ssl parameters
+/*=======================================================================*/
+//! ssl version
+#define RSI_SSL_VERSION 0
+
+//! ssl ciphers
+#define RSI_SSL_CIPHERS SSL_ALL_CIPHERS
+
+//! Enable TCP over SSL with TLS version depends on remote side
+#define PROTOCOL_DFLT_VERSION BIT(0)
+
+//! Enable TCP over SSL with TLS version 1.0
+#define PROTOCOL_TLS_1_0 (BIT(0) | BIT(13))
+
+//! Enable TCP over SSL with TLS version 1.1
+#define PROTOCOL_TLS_1_1 (BIT(0) | BIT(14))
+
+//! Enable TCP over SSL with TLS version 1.2
+#define PROTOCOL_TLS_1_2 (BIT(0) | BIT(15))
+/*=======================================================================*/
+//! Power save command parameters
+/*=======================================================================*/
+//! set handshake type of power mode
+#define RSI_HAND_SHAKE_TYPE MSG_BASED
+
+//! 0 - LP, 1- ULP mode with RAM retention and 2 - ULP with Non RAM retention
+#define RSI_SELECT_LP_OR_ULP_MODE RSI_ULP_WITH_RAM_RET
+
+//! set DTIM aligment required
+//! 0 - module wakes up at beacon which is just before or equal to listen_interval
+//! 1 - module wakes up at DTIM beacon which is just before or equal to listen_interval
+#define RSI_DTIM_ALIGNED_TYPE 0
+
+//! Monitor interval for the FAST PSP mode
+//! default is 50 ms, and this parameter is valid for FAST PSP only
+#define RSI_MONITOR_INTERVAL 50
+
+//! Number of DTIMs to skip during powersave
+#define RSI_NUM_OF_DTIM_SKIP 0
+
+//! WMM PS parameters
+//! set wmm enable or disable
+#define RSI_WMM_PS_ENABLE RSI_DISABLE
+
+//! set wmm enable or disable
+//! 0- TX BASED 1 - PERIODIC
+#define RSI_WMM_PS_TYPE 0
+
+//! set wmm wake up interval
+#define RSI_WMM_PS_WAKE_INTERVAL 20
+
+//! set wmm UAPSD bitmap
+#define RSI_WMM_PS_UAPSD_BITMAP 15
+
+/*=======================================================================*/
+//! Socket configuration
+/*=======================================================================*/
+//! RSI_ENABLE or RSI_DISABLE High performance socket
+#define HIGH_PERFORMANCE_ENABLE RSI_ENABLE //@ RSI_ENABLE or RSI_DISABLE High performance socket
+#define TOTAL_SOCKETS 10 //@ Total number of sockets. TCP TX + TCP RX + UDP TX + UDP RX
+#define TOTAL_TCP_SOCKETS 4 //@ Total TCP sockets. TCP TX + TCP RX
+#define TOTAL_UDP_SOCKETS 4 //@ Total UDP sockets. UDP TX + UDP RX
+#define TCP_TX_ONLY_SOCKETS 0 //@ Total TCP TX only sockets. TCP TX
+#define TCP_RX_ONLY_SOCKETS 0 //@ Total TCP RX only sockets. TCP RX
+#define UDP_TX_ONLY_SOCKETS 0 //@ Total UDP TX only sockets. UDP TX
+#define UDP_RX_ONLY_SOCKETS 0 //@ Total UDP RX only sockets. UDP RX
+#define TCP_RX_HIGH_PERFORMANCE_SOCKETS 1 //@ Total TCP RX High Performance sockets
+#define TCP_RX_WINDOW_SIZE_CAP 10 //@ TCP RX Window size
+#define TCP_RX_WINDOW_DIV_FACTOR 10 //@ TCP RX Window division factor
+/*=======================================================================*/
+
+//! Socket Create parameters
+/*=======================================================================*/
+
+//! Initial timeout for Socket
+#define RSI_SOCKET_KEEPALIVE_TIMEOUT 1200
+
+//! VAP ID for Concurrent mode
+#define RSI_VAP_ID 0
+
+//! Timeout for join or scan
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Timeout support
+#define RSI_TIMEOUT_SUPPORT RSI_DISABLE
+
+//! roaming threshold value
+#define RSI_TIMEOUT_BIT_MAP 1
+
+//! roaming hysterisis value
+#define RSI_TIMEOUT_VALUE 1500
+
+//! Timeout for ping request
+/*=======================================================================*/
+
+//! Timeout for PING_REQUEST
+#define RSI_PING_REQ_TIMEOUT_MS 1000
+
+//! Provide HTTP/HTTPS response status code indication to application e.g 200, 404 etc
+/*=======================================================================*/
+//! Enable or Diable feature
+#define RSI_HTTP_STATUS_INDICATION_EN RSI_DISABLE
+/*=======================================================================*/
+
+//! Store Config Profile parameters
+/*=======================================================================*/
+
+//! Client profile
+#define RSI_WLAN_PROFILE_CLIENT 0
+//! P2P profile
+#define RSI_WLAN_PROFILE_P2P 1
+//! EAP profile
+#define RSI_WLAN_PROFILE_EAP 2
+//! AP profile
+#define RSI_WLAN_PROFILE_AP 6
+//! All profiles
+#define RSI_WLAN_PROFILE_ALL 0xFF
+
+//! AP Config Profile Parameters
+/*==============================================================================*/
+
+//! Transmission data rate. Physical rate at which data has to be transmitted.
+#define RSI_CONFIG_AP_DATA_RATE RSI_DATA_RATE_AUTO
+//! To set wlan feature select bit map
+#define RSI_CONFIG_AP_WLAN_FEAT_BIT_MAP (FEAT_SECURITY_PSK)
+//! TCP/IP feature select bitmap for selecting TCP/IP features
+#define RSI_CONFIG_AP_TCP_IP_FEAT_BIT_MAP (TCP_IP_FEAT_DHCPV4_SERVER)
+//! To set custom feature select bit map
+#define RSI_CONFIG_AP_CUSTOM_FEAT_BIT_MAP 0
+//! Tx power level
+#define RSI_CONFIG_AP_TX_POWER RSI_POWER_LEVEL_HIGH
+//! AP SSID
+#define RSI_CONFIG_AP_SSID "SILABS_AP"
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_CONFIG_AP_BAND RSI_BAND_2P4GHZ
+//! To configure AP channle number
+#define RSI_CONFIG_AP_CHANNEL 6
+//! To configure security type
+#define RSI_CONFIG_AP_SECURITY_TYPE RSI_WPA
+//! To configure encryption type
+#define RSI_CONFIG_AP_ENCRYPTION_TYPE 1
+//! To configure PSK
+#define RSI_CONFIG_AP_PSK "1234567890"
+//! To configure beacon interval
+#define RSI_CONFIG_AP_BEACON_INTERVAL 100
+//! To configure DTIM period
+#define RSI_CONFIG_AP_DTIM 2
+//! This parameter is used to configure keep alive type
+#define RSI_CONFIG_AP_KEEP_ALIVE_TYPE 0 //! RSI_NULL_BASED_KEEP_ALIVE
+
+#define RSI_CONFIG_AP_KEEP_ALIVE_COUNTER 0 //! 100
+//! This parameter is used to configure keep alive period
+#define RSI_CONFIG_AP_KEEP_ALIVE_PERIOD 100
+//! This parameter is used to configure maximum stations supported
+#define RSI_CONFIG_AP_MAX_STATIONS_COUNT 4
+//! P2P Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_AP_TCP_STACK_USED BIT(0)
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_AP_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_AP_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_AP_GATEWAY_ADDRESS 0x0A0AA8C0
+
+//! Client Profile Parameters
+/* ===================================================================================== */
+
+//! To configure data rate
+#define RSI_CONFIG_CLIENT_DATA_RATE RSI_DATA_RATE_AUTO
+//! To configure wlan feature bitmap
+#define RSI_CONFIG_CLIENT_WLAN_FEAT_BIT_MAP 0
+//! To configure tcp/ip feature bitmap
+#define RSI_CONFIG_CLIENT_TCP_IP_FEAT_BIT_MAP BIT(2)
+//! To configure custom feature bit map
+#define RSI_CONFIG_CLIENT_CUSTOM_FEAT_BIT_MAP 0
+//! To configure TX power
+#define RSI_CONFIG_CLIENT_TX_POWER RSI_POWER_LEVEL_HIGH
+//! To configure listen interval
+#define RSI_CONFIG_CLIENT_LISTEN_INTERVAL 0
+//! To configure SSID
+#define RSI_CONFIG_CLIENT_SSID "Matter_9116"
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_CONFIG_CLIENT_BAND RSI_BAND_2P4GHZ
+//! To configure channel number
+#define RSI_CONFIG_CLIENT_CHANNEL 0
+//! To configure security type
+#define RSI_CONFIG_CLIENT_SECURITY_TYPE 0 // RSI_WPA
+//! To configure encryption type
+#define RSI_CONFIG_CLIENT_ENCRYPTION_TYPE 0
+//! To configure PSK
+#define RSI_CONFIG_CLIENT_PSK "1234567890"
+//! To configure PMK
+#define RSI_CONFIG_CLIENT_PMK ""
+//! Client Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_CLIENT_TCP_STACK_USED BIT(0)
+//! DHCP mode 1- Enable 0- Disable
+//! If DHCP mode is disabled given IP statically
+#define RSI_CONFIG_CLIENT_DHCP_MODE RSI_DHCP
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_CLIENT_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_CLIENT_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x010AA8C0 == 192.168.10.1
+#define RSI_CONFIG_CLIENT_GATEWAY_ADDRESS 0x010AA8C0
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_CLIENT_SCAN_FEAT_BITMAP 0
+//! Scan channel magic code
+#define RSI_CONFIG_CLIENT_MAGIC_CODE 0x4321
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_CLIENT_SCAN_CHAN_BITMAP_2_4_GHZ 0
+//! scan channle bit map in 5GHz band ,valid if given channel to scan is 0
+#define RSI_CONFIG_CLIENT_SCAN_CHAN_BITMAP_5_0_GHZ 0
+
+//! EAP Client Profile Parameters
+/* =========================================================================== */
+
+//! To configure data rate
+#define RSI_CONFIG_EAP_DATA_RATE RSI_DATA_RATE_AUTO
+//! To configure wlan feature bitmap
+#define RSI_CONFIG_EAP_WLAN_FEAT_BIT_MAP 0
+//! To configure tcp/ip feature bitmap
+#define RSI_CONFIG_EAP_TCP_IP_FEAT_BIT_MAP BIT(2)
+//! To configure custom feature bit map
+#define RSI_CONFIG_EAP_CUSTOM_FEAT_BIT_MAP 0
+//! To configure EAP TX power
+#define RSI_CONFIG_EAP_TX_POWER RSI_POWER_LEVEL_HIGH
+//! To Configure scan channel feature bitmap
+#define RSI_CONFIG_EAP_SCAN_FEAT_BITMAP 0
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_EAP_CHAN_MAGIC_CODE 0 // 0x4321
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_EAP_SCAN_CHAN_BITMAP_2_4_GHZ 0
+//! scan channle bit map in 5GHz band ,valid if given channel to scan is 0
+#define RSI_CONFIG_EAP_SCAN_CHAN_BITMAP_5_0_GHZ 0
+//! To configure SSID
+#define RSI_CONFIG_EAP_SSID "SILABS_AP"
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_CONFIG_EAP_BAND RSI_BAND_2P4GHZ
+//! To set security type
+#define RSI_CONFIG_EAP_SECURITY_TYPE RSI_WPA2_EAP
+//! To set encryption type
+#define RSI_CONFIG_EAP_ENCRYPTION_TYPE 0
+//! To set channel number
+#define RSI_CONFIG_EAP_CHANNEL 0
+//! Enterprise method ,should be one of among TLS, TTLS, FAST or PEAP
+#define RSI_CONFIG_EAP_METHOD "TLS"
+//! This parameter is used to configure the module in Enterprise security mode
+#define RSI_CONFIG_EAP_INNER_METHOD "\"auth=MSCHAPV2\""
+//! To configure EAP user identity
+#define RSI_CONFIG_EAP_USER_IDENTITY "\"user1\""
+//! TO configure EAP password
+#define RSI_CONFIG_EAP_PASSWORD "\"test123\""
+//! EAP Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_EAP_TCP_STACK_USED BIT(0)
+//! DHCP mode 1- Enable 0- Disable
+//! If DHCP mode is disabled given IP statically
+#define RSI_CONFIG_EAP_DHCP_MODE RSI_DHCP
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_EAP_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_EAP_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x010AA8C0 == 192.168.10.1
+#define RSI_CONFIG_EAP_GATEWAY_ADDRESS 0x010AA8C0
+
+//! P2P Profile parameters
+/* ================================================================================= */
+
+//! To configure data rate
+#define RSI_CONFIG_P2P_DATA_RATE RSI_DATA_RATE_AUTO
+//! To configure wlan feature bitmap
+#define RSI_CONFIG_P2P_WLAN_FEAT_BIT_MAP 0
+//! To configure P2P tcp/ip feature bitmap
+#define RSI_CONFIG_P2P_TCP_IP_FEAT_BIT_MAP BIT(2)
+//! To configure P2P custom feature bitmap
+#define RSI_CONFIG_P2P_CUSTOM_FEAT_BIT_MAP 0
+//! TO configure P2P tx power level
+#define RSI_CONFIG_P2P_TX_POWER RSI_POWER_LEVEL_HIGH
+//! Set P2P go intent
+#define RSI_CONFIG_P2P_GO_INTNET 16 //! Support only Autonomous GO mode
+//! Set device name
+#define RSI_CONFIG_P2P_DEVICE_NAME "WSC1.1"
+//! Set device operating channel
+#define RSI_CONFIG_P2P_OPERATING_CHANNEL 11
+//! Set SSID postfix
+#define RSI_CONFIG_P2P_SSID_POSTFIX "WSC_1_0_0"
+//! Set P2P join SSID
+#define RSI_CONFIG_P2P_JOIN_SSID "SILABS_AP"
+//! Set psk key
+#define RSI_CONFIG_P2P_PSK_KEY "12345678"
+//! P2P Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_P2P_TCP_STACK_USED BIT(0)
+//! DHCP mode 1- Enable 0- Disable
+//! If DHCP mode is disabled given IP statically
+#define RSI_CONFIG_P2P_DHCP_MODE 1
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_P2P_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_P2P_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x010AA8C0 == 192.168.10.1
+#define RSI_CONFIG_P2P_GATEWAY_ADDRESS 0x010AA8C0
+
+#endif
diff --git a/examples/platform/silabs/SiWx917/rs911x/wfx_rsi.h b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi.h
new file mode 100644
index 0000000..380fc8f
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi.h
@@ -0,0 +1,98 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WFX_RSI_H_
+#define _WFX_RSI_H_
+/*
+ * Interface to RSI Sapis
+ */
+
+#define WFX_RSI_WLAN_TASK_SZ (1024 + 512 + 256) /* Unknown how big this should be */
+#define WFX_RSI_TASK_SZ (1024 + 1024) /* Stack for the WFX/RSI task */
+#define WFX_RSI_BUF_SZ (1024 * 10) /* May need tweak */
+#define WFX_RSI_CONFIG_MAX_JOIN 5 /* Max join retries */
+#define WFX_RSI_NUM_TIMERS 2 /* Number of RSI timers to alloc */
+
+/*
+ * Various events fielded by the wfx_rsi task
+ * Make sure that we only use 8 bits (otherwise freeRTOS - may need some changes)
+ */
+#define WFX_EVT_STA_CONN 0x01
+#define WFX_EVT_STA_DISCONN 0x02
+#define WFX_EVT_AP_START 0x04
+#define WFX_EVT_AP_STOP 0x08
+#define WFX_EVT_SCAN 0x10 /* This is used as scan result and start */
+#define WFX_EVT_STA_START_JOIN 0x20
+#define WFX_EVT_STA_DO_DHCP 0x40
+#define WFX_EVT_STA_DHCP_DONE 0x80
+
+#define WFX_RSI_ST_DEV_READY 0x01
+#define WFX_RSI_ST_AP_READY 0x02
+#define WFX_RSI_ST_STA_PROVISIONED 0x04
+#define WFX_RSI_ST_STA_CONNECTING 0x08
+#define WFX_RSI_ST_STA_CONNECTED 0x10
+#define WFX_RSI_ST_STA_DHCP_DONE 0x40 /* Requested to do DHCP after conn */
+#define WFX_RSI_ST_STA_MODE 0x80 /* Enable Station Mode */
+#define WFX_RSI_ST_AP_MODE 0x100 /* Enable AP Mode */
+#define WFX_RSI_ST_STA_READY (WFX_RSI_ST_STA_CONNECTED | WFX_RSI_ST_STA_DHCP_DONE)
+#define WFX_RSI_ST_STARTED 0x200 /* RSI task started */
+#define WFX_RSI_ST_SCANSTARTED 0x400 /* Scan Started */
+
+struct wfx_rsi
+{
+ EventGroupHandle_t events;
+ TaskHandle_t drv_task;
+ TaskHandle_t wlan_task;
+ uint16_t dev_state;
+ uint16_t ap_chan; /* The chan our STA is using */
+ wfx_wifi_provision_t sec;
+#ifdef SL_WFX_CONFIG_SCAN
+ void (*scan_cb)(wfx_wifi_scan_result_t *);
+ char * scan_ssid; /* Which one are we scanning for */
+#endif
+#ifdef SL_WFX_CONFIG_SOFTAP
+ sl_wfx_mac_address_t softap_mac;
+#endif
+ sl_wfx_mac_address_t sta_mac;
+ sl_wfx_mac_address_t ap_mac; /* To which our STA is connected */
+ sl_wfx_mac_address_t ap_bssid; /* To which our STA is connected */
+ uint16_t join_retries;
+ uint8_t ip4_addr[4]; /* Not sure if this is enough */
+};
+#define RSI_SCAN_RESP_SZ 54
+
+extern struct wfx_rsi wfx_rsi;
+#ifdef __cplusplus
+extern "C" {
+#endif
+void wfx_rsidev_init(void);
+void wfx_rsi_task(void * arg);
+void efr32Log(const char * aFormat, ...);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+void wfx_ip_changed_notify(int got_ip);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap);
+int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info);
+int32_t wfx_rsi_reset_count();
+int32_t wfx_rsi_disconnect();
+#define WFX_RSI_LOG(...) efr32Log(__VA_ARGS__);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WFX_RSI_H_ */
diff --git a/examples/platform/silabs/SiWx917/rs911x/wfx_rsi_host.c b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi_host.c
new file mode 100644
index 0000000..a55e0ae
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi_host.c
@@ -0,0 +1,440 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+/* wfxRsi Task will use as its stack */
+StackType_t wfxRsiTaskStack[WFX_RSI_TASK_SZ] = { 0 };
+
+/* Structure that will hold the TCB of the wfxRsi Task being created. */
+StaticTask_t wfxRsiTaskBuffer;
+
+/*********************************************************************
+ * @fn sl_status_t wfx_wifi_start(void)
+ * @brief
+ * Called from ConnectivityManagerImpl.cpp - to enable the device
+ * Create the RSI task and let it deal with life.
+ * @param[in] None
+ * @return Returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ ***********************************************************************/
+sl_status_t wfx_wifi_start(void)
+{
+ if (wfx_rsi.dev_state & WFX_RSI_ST_STARTED)
+ {
+ WFX_RSI_LOG("%s: already started.", __func__);
+ return SL_STATUS_OK;
+ }
+ wfx_rsi.dev_state |= WFX_RSI_ST_STARTED;
+ WFX_RSI_LOG("%s: starting..", __func__);
+ /*
+ * Create the Wifi driver task
+ */
+ wfx_rsi.wlan_task = xTaskCreateStatic(wfx_rsi_task, "wfx_rsi", WFX_RSI_TASK_SZ, NULL, WLAN_DRIVER_TASK_PRIORITY,
+ wfxRsiTaskStack, &wfxRsiTaskBuffer);
+
+ if (NULL == wfx_rsi.wlan_task)
+ {
+ WFX_RSI_LOG("%s: error: failed to create task.", __func__);
+ return SL_STATUS_FAIL;
+ }
+ return SL_STATUS_OK;
+}
+
+/*********************************************************************
+ * @fn void wfx_enable_sta_mode(void)
+ * @brief
+ * driver enable the STA mode
+ * @param[in] None
+ * @return None
+ ***********************************************************************/
+void wfx_enable_sta_mode(void)
+{
+ wfx_rsi.dev_state |= WFX_RSI_ST_STA_MODE;
+}
+
+/*********************************************************************
+ * @fn bool wfx_is_sta_mode_enabled(void)
+ * @brief
+ * driver enabled the STA mode
+ * @param[in] None
+ * @return mode
+ ***********************************************************************/
+bool wfx_is_sta_mode_enabled(void)
+{
+ bool mode;
+ mode = !!(wfx_rsi.dev_state & WFX_RSI_ST_STA_MODE);
+ // WFX_RSI_LOG("%s: %d", __func__, (mode ? "yes" : "no"));
+ return mode;
+}
+
+/*********************************************************************
+ * @fn sl_wfx_state_t wfx_get_wifi_state(void)
+ * @brief
+ * get the wifi state
+ * @param[in] None
+ * @return return SL_WFX_NOT_INIT if successful,
+ * SL_WFX_started otherwise
+ ***********************************************************************/
+sl_wfx_state_t wfx_get_wifi_state(void)
+{
+ if (wfx_rsi.dev_state & WFX_RSI_ST_STA_DHCP_DONE)
+ {
+ return SL_WFX_STA_INTERFACE_CONNECTED;
+ }
+ if (wfx_rsi.dev_state & WFX_RSI_ST_DEV_READY)
+ {
+ return SL_WFX_STARTED;
+ }
+ return SL_WFX_NOT_INIT;
+}
+
+/*********************************************************************
+ * @fn sl_wfx_state_t wfx_get_wifi_state(void)
+ * @brief
+ * get the wifi mac address
+ * @param[in] Interface:
+ * @param[in] addr : address
+ * @return
+ * None
+ ***********************************************************************/
+void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr)
+{
+ sl_wfx_mac_address_t * mac;
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+ mac = (interface == SL_WFX_SOFTAP_INTERFACE) ? &wfx_rsi.softap_mac : &wfx_rsi.sta_mac;
+#else
+ mac = &wfx_rsi.sta_mac;
+#endif
+ *addr = *mac;
+ WFX_RSI_LOG("%s: %02x:%02x:%02x:%02x:%02x:%02x", __func__, mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3],
+ mac->octet[4], mac->octet[5]);
+}
+
+/*********************************************************************
+ * @fn void wfx_set_wifi_provision(wfx_wifi_provision_t *cfg)
+ * @brief
+ * Driver set the wifi provision
+ * @param[in] cfg: wifi configuration
+ * @return
+ * None
+ ***********************************************************************/
+void wfx_set_wifi_provision(wfx_wifi_provision_t * cfg)
+{
+ WFX_RSI_LOG("%s: SSID: %s", __func__, &wfx_rsi.sec.ssid[0]);
+
+ wfx_rsi.sec = *cfg;
+ wfx_rsi.dev_state |= WFX_RSI_ST_STA_PROVISIONED;
+}
+
+/*********************************************************************
+ * @fn bool wfx_get_wifi_provision(wfx_wifi_provision_t *wifiConfig)
+ * @brief
+ * Driver get the wifi provision
+ * @param[in] wifiConfig: wifi configuration
+ * @return return false if successful,
+ * true otherwise
+ ***********************************************************************/
+bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig)
+{
+ if (wifiConfig != NULL)
+ {
+ if (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED)
+ {
+ *wifiConfig = wfx_rsi.sec;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*********************************************************************
+ * @fn bool wfx_is_sta_provisioned(void)
+ * @brief
+ * Driver is STA provisioned
+ * @param[in] None
+ * @return None
+ ***********************************************************************/
+bool wfx_is_sta_provisioned(void)
+{
+ bool status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED) ? true : false;
+ WFX_RSI_LOG("%s: status: SSID -> %s: %s", __func__, &wfx_rsi.sec.ssid[0], (status ? "provisioned" : "not provisioned"));
+ return status;
+}
+
+/*********************************************************************
+ * @fn void wfx_clear_wifi_provision(void)
+ * @brief
+ * Driver is clear the wifi provision
+ * @param[in] None
+ * @return None
+ ***********************************************************************/
+void wfx_clear_wifi_provision(void)
+{
+ memset(&wfx_rsi.sec, 0, sizeof(wfx_rsi.sec));
+ wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_PROVISIONED;
+ WFX_RSI_LOG("%s: completed.", __func__);
+}
+
+/*************************************************************************
+ * @fn sl_status_t wfx_connect_to_ap(void)
+ * @brief
+ * Start a JOIN command to the AP - Done by the wfx_rsi task
+ * @param[in] None
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_INVALID_CONFIGURATION otherwise
+ ****************************************************************************/
+sl_status_t wfx_connect_to_ap(void)
+{
+ if (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED)
+ {
+ WFX_RSI_LOG("%s: connecting to access point -> SSID: %s, PSK:%s", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0]);
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN);
+ }
+ else
+ {
+ WFX_RSI_LOG("%s: error: access point not provisioned", __func__);
+ return SL_STATUS_INVALID_CONFIGURATION;
+ }
+ return SL_STATUS_OK;
+}
+
+/*********************************************************************
+ * @fn void wfx_setup_ip6_link_local(sl_wfx_interface_t whichif)
+ * @brief
+ * Implement the ipv6 setup
+ * @param[in] whichif:
+ * @return None
+ ***********************************************************************/
+void wfx_setup_ip6_link_local(sl_wfx_interface_t whichif)
+{
+ /*
+ * TODO: Implement IPV6 setup, currently in wfx_rsi_task()
+ * This is hooked with MATTER code.
+ */
+ WFX_RSI_LOG("%s: warning: not implemented.", __func__);
+}
+
+/*********************************************************************
+ * @fn bool wfx_is_sta_connected(void)
+ * @brief
+ * called fuction when driver is connected to STA
+ * @param[in] None
+ * @return returns ture if successful,
+ * false otherwise
+ ***********************************************************************/
+bool wfx_is_sta_connected(void)
+{
+ bool status;
+ status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED) ? true : false;
+ WFX_RSI_LOG("%s: status: %s", __func__, (status ? "connected" : "not connected"));
+ return status;
+}
+
+/*********************************************************************
+ * @fn wifi_mode_t wfx_get_wifi_mode()
+ * @brief
+ * get the wifi mode
+ * @param[in] None
+ * @return return WIFI_MODE_NULL if successful,
+ * WIFI_MODE_STA otherwise
+ ***********************************************************************/
+wifi_mode_t wfx_get_wifi_mode()
+{
+ if (wfx_rsi.dev_state & WFX_RSI_ST_DEV_READY)
+ return WIFI_MODE_STA;
+ return WIFI_MODE_NULL;
+}
+
+/*********************************************************************
+ * @fn sl_status_t wfx_sta_discon(void)
+ * @brief
+ * called fuction when STA disconnected
+ * @param[in] None
+ * @return return SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ ***********************************************************************/
+sl_status_t wfx_sta_discon(void)
+{
+ WFX_RSI_LOG("%s: started.", __func__);
+ int32_t status;
+ status = wfx_rsi_disconnect();
+ wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTED;
+ WFX_RSI_LOG("%s: completed.", __func__);
+ return status;
+}
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+/*********************************************************************
+ * @fn bool wfx_have_ipv4_addr(sl_wfx_interface_t which_if)
+ * @brief
+ * called fuction when driver have ipv4 address
+ * @param[in] which_if:
+ * @return returns ture if successful,
+ * false otherwise
+ ***********************************************************************/
+bool wfx_have_ipv4_addr(sl_wfx_interface_t which_if)
+{
+ bool status = false;
+ if (which_if == SL_WFX_STA_INTERFACE)
+ {
+ status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_DHCP_DONE) ? true : false;
+ }
+ else
+ {
+ status = false; /* TODO */
+ }
+ WFX_RSI_LOG("%s: status: %d", __func__, status);
+ return status;
+}
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+
+/*********************************************************************
+ * @fn bool wfx_have_ipv6_addr(sl_wfx_interface_t which_if)
+ * @brief
+ * called fuction when driver have ipv6 address
+ * @param[in] which_if:
+ * @return returns ture if successful,
+ * false otherwise
+ ***********************************************************************/
+bool wfx_have_ipv6_addr(sl_wfx_interface_t which_if)
+{
+ bool status = false;
+ if (which_if == SL_WFX_STA_INTERFACE)
+ {
+ status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED) ? true : false;
+ }
+ else
+ {
+ status = false; /* TODO */
+ }
+ WFX_RSI_LOG("%s: status: %d", __func__, status);
+ return status;
+}
+
+/*********************************************************************
+ * @fn bool wfx_hw_ready(void)
+ * @brief
+ * called fuction when driver ready
+ * @param[in] None
+ * @return returns ture if successful,
+ * false otherwise
+ ***********************************************************************/
+bool wfx_hw_ready(void)
+{
+ return (wfx_rsi.dev_state & WFX_RSI_ST_DEV_READY) ? true : false;
+}
+
+/*********************************************************************
+ * @fn int32_t wfx_get_ap_info(wfx_wifi_scan_result_t *ap)
+ * @brief
+ * get the access point information
+ * @param[in] ap: access point
+ * @return
+ * access point information
+ ***********************************************************************/
+int32_t wfx_get_ap_info(wfx_wifi_scan_result_t * ap)
+{
+ return wfx_rsi_get_ap_info(ap);
+}
+
+/*********************************************************************
+ * @fn int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t *extra_info)
+ * @brief
+ * get the access point extra information
+ * @param[in] extra_info:access point extra information
+ * @return
+ * access point extra information
+ ***********************************************************************/
+int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t * extra_info)
+{
+ return wfx_rsi_get_ap_ext(extra_info);
+}
+
+/***************************************************************************
+ * @fn int32_t wfx_reset_counts(){
+ * @brief
+ * get the driver reset count
+ * @param[in] None
+ * @return
+ * reset count
+ *****************************************************************************/
+int32_t wfx_reset_counts()
+{
+ return wfx_rsi_reset_count();
+}
+
+#ifdef SL_WFX_CONFIG_SCAN
+/*******************************************************************************
+ * @fn bool wfx_start_scan(char *ssid, void (*callback)(wfx_wifi_scan_result_t *))
+ * @brief
+ * called fuction when driver start scaning
+ * @param[in] ssid:
+ * @return returns ture if successful,
+ * false otherwise
+ *******************************************************************************/
+bool wfx_start_scan(char * ssid, void (*callback)(wfx_wifi_scan_result_t *))
+{
+ int sz;
+
+ if (wfx_rsi.scan_cb)
+ return false; /* Already in progress */
+ if (ssid)
+ {
+ sz = strlen(ssid);
+ if ((wfx_rsi.scan_ssid = (char *) pvPortMalloc(sz + 1)) == (char *) 0)
+ {
+ return false;
+ }
+ strcpy(wfx_rsi.scan_ssid, ssid);
+ }
+ wfx_rsi.scan_cb = callback;
+ xEventGroupSetBits(wfx_rsi.events, WFX_EVT_SCAN);
+
+ return true;
+}
+
+/***************************************************************************
+ * @fn void wfx_cancel_scan(void)
+ * @brief
+ * called function when driver cancel scaning
+ * @param[in] None
+ * @return
+ * None
+ *****************************************************************************/
+void wfx_cancel_scan(void)
+{
+ /* Not possible */
+ WFX_RSI_LOG("%s: cannot cancel scan", __func__);
+}
+#endif /* SL_WFX_CONFIG_SCAN */
diff --git a/examples/platform/silabs/SiWx917/rs911x/wfx_rsidev.c b/examples/platform/silabs/SiWx917/rs911x/wfx_rsidev.c
new file mode 100644
index 0000000..8d8a3c1
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/wfx_rsidev.c
@@ -0,0 +1,272 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef _WFX_NOT_USED_USING_HAL_INSTEAD_
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+
+/* Need Lwip stuff before rsi is included */
+#include "wfx_host_events.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "rsi_common_apis.h"
+#include "rsi_data_types.h"
+#include "rsi_error.h"
+#include "rsi_nwk.h"
+#include "rsi_socket.h"
+#include "rsi_utils.h"
+#include "rsi_wlan.h"
+#include "rsi_wlan_apis.h"
+#include "rsi_wlan_config.h"
+#include "task.h"
+
+#include "wfx_host_pinout.h"
+#include "wfx_rsi.h"
+
+/* The following stuff comes from hal/rsi_hal_mcu_interrupt.c */
+static void (*rsi_intr_cb)(void);
+/*********************************************************************
+ * @fn void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void))
+ * @brief
+ * get the hal intr configuration
+ * @param[in] rsi_interrupt_handler:
+ * @return
+ * None
+ ***********************************************************************/
+void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void))
+{
+ rsi_intr_cb = rsi_interrupt_handler;
+}
+
+/***********************************************************************
+ * @fn static void wfx_spi_wakeup_irq_callback(uint8_t irqNumber)
+ * @brief
+ * end of stuff from hal/rsi_hal_mcu_interrupt.c
+ * @param[in] irqNumber:
+ * @return None
+ * **********************************************************************/
+static void wfx_spi_wakeup_irq_callback(uint8_t irqNumber)
+{
+ BaseType_t bus_task_woken;
+ uint32_t interrupt_mask;
+
+ if (irqNumber != SL_WFX_HOST_PINOUT_SPI_IRQ)
+ return;
+ // Get and clear all pending GPIO interrupts
+ interrupt_mask = GPIO_IntGet();
+ GPIO_IntClear(interrupt_mask);
+ if (rsi_intr_cb)
+ (*rsi_intr_cb)();
+}
+
+/***********************************************************************
+ * @fn static void wfx_host_gpio_init(void)
+ * @brief
+ * function called when host gpio intialization
+ * @param[in] None
+ * @return None
+ * **********************************************************************/
+static void wfx_host_gpio_init(void)
+{
+ // Enable GPIO clock.
+ CMU_ClockEnable(cmuClock_GPIO, true);
+
+ // Configure WF200 reset pin.
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN, gpioModePushPull, PINOUT_CLEAR);
+ // Configure WF200 WUP pin.
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN, gpioModePushPull, PINOUT_CLEAR);
+
+ // GPIO used as IRQ.
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, gpioModeInputPull, PINOUT_CLEAR);
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+
+ // Set up interrupt based callback function - trigger on both edges.
+ GPIOINT_Init();
+ GPIO_ExtIntConfig(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, SL_WFX_HOST_PINOUT_SPI_IRQ, true, false,
+ true);
+ GPIOINT_CallbackRegister(SL_WFX_HOST_PINOUT_SPI_IRQ, wfx_spi_wakeup_irq_callback);
+
+ // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!)
+ NVIC_SetPriority(GPIO_EVEN_IRQn, WFX_GPIO_NVIC_PRIORITY);
+ NVIC_SetPriority(GPIO_ODD_IRQn, WFX_GPIO_NVIC_PRIORITY);
+}
+
+#define USART SL_WFX_HOST_PINOUT_SPI_PERIPHERAL
+
+/***********************************************************************
+ * @fn static int sl_wfx_host_spi_set_config(void *usart)
+ * @brief
+ * set the configuration of spi
+ * @param[in] usart:
+ * @return returns 0 if successful,
+ * -1 otherwise
+ * **********************************************************************/
+static int sl_wfx_host_spi_set_config(void * usart)
+{
+ int ret = -1;
+
+ if (0)
+ {
+#if defined(USART0)
+ }
+ else if (usart == USART0)
+ {
+ usart_clock = cmuClock_USART0;
+ usart_tx_signal = dmadrvPeripheralSignal_USART0_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USART0_RXDATAV;
+ ret = 0;
+#endif
+#if defined(USART1)
+ }
+ else if (usart == USART1)
+ {
+ usart_clock = cmuClock_USART1;
+ usart_tx_signal = dmadrvPeripheralSignal_USART1_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USART1_RXDATAV;
+ ret = 0;
+#endif
+#if defined(USART2)
+ }
+ else if (usart == USART2)
+ {
+ usart_clock = cmuClock_USART2;
+ usart_tx_signal = dmadrvPeripheralSignal_USART2_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USART2_RXDATAV;
+ ret = 0;
+#endif
+#if defined(USART3)
+ }
+ else if (usart == USART3)
+ {
+ usart_clock = cmuClock_USART3;
+ usart_tx_signal = dmadrvPeripheralSignal_USART3_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USART3_RXDATAV;
+ ret = 0;
+#endif
+#if defined(USART4)
+ }
+ else if (usart == USART4)
+ {
+ usart_clock = cmuClock_USART4;
+ usart_tx_signal = dmadrvPeripheralSignal_USART4_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USART4_RXDATAV;
+ ret = 0;
+#endif
+#if defined(USART5)
+ }
+ else if (usart == USART5)
+ {
+ usart_clock = cmuClock_USART5;
+ usart_tx_signal = dmadrvPeripheralSignal_USART5_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USART5_RXDATAV;
+ ret = 0;
+#endif
+#if defined(USARTRF0)
+ }
+ else if (usart == USARTRF0)
+ {
+ usart_clock = cmuClock_USARTRF0;
+ usart_tx_signal = dmadrvPeripheralSignal_USARTRF0_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USARTRF0_RXDATAV;
+ ret = 0;
+#endif
+#if defined(USARTRF1)
+ }
+ else if (usart == USARTRF1)
+ {
+ usart_clock = cmuClock_USARTRF1;
+ usart_tx_signal = dmadrvPeripheralSignal_USARTRF1_TXBL;
+ usart_rx_signal = dmadrvPeripheralSignal_USARTRF1_RXDATAV;
+ ret = 0;
+#endif
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_init_bus(void)
+ * @brief
+ * Initialize SPI peripheral
+ * @param[in] None
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_init_bus(void)
+{
+ int res;
+
+ // Initialize and enable the USART
+ USART_InitSync_TypeDef usartInit = USART_INITSYNC_DEFAULT;
+
+ res = sl_wfx_host_spi_set_config(USART);
+ if (res != SPI_CONFIG_SUCCESS)
+ {
+ return SL_STATUS_FAIL;
+ }
+
+ spi_enabled = true;
+ dummy_tx_data = 0;
+ usartInit.baudrate = 36000000u;
+ usartInit.msbf = true;
+ CMU_ClockEnable(cmuClock_HFPER, true);
+ CMU_ClockEnable(cmuClock_GPIO, true);
+ CMU_ClockEnable(usart_clock, true);
+ USART_InitSync(USART, &usartInit);
+ USART->CTRL |= (1u << _USART_CTRL_SMSDELAY_SHIFT);
+ USART->ROUTELOC0 =
+ (USART->ROUTELOC0 & ~(_USART_ROUTELOC0_TXLOC_MASK | _USART_ROUTELOC0_RXLOC_MASK | _USART_ROUTELOC0_CLKLOC_MASK)) |
+ (SL_WFX_HOST_PINOUT_SPI_TX_LOC << _USART_ROUTELOC0_TXLOC_SHIFT) |
+ (SL_WFX_HOST_PINOUT_SPI_RX_LOC << _USART_ROUTELOC0_RXLOC_SHIFT) |
+ (SL_WFX_HOST_PINOUT_SPI_CLK_LOC << _USART_ROUTELOC0_CLKLOC_SHIFT);
+
+ USART->ROUTEPEN = USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_CLKPEN;
+ GPIO_DriveStrengthSet(SL_WFX_HOST_PINOUT_SPI_CLK_PORT, gpioDriveStrengthStrongAlternateStrong);
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_TX_PORT, SL_WFX_HOST_PINOUT_SPI_TX_PIN, gpioModePushPull, PINOUT_CLEAR);
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_RX_PORT, SL_WFX_HOST_PINOUT_SPI_RX_PIN, gpioModeInput, PINOUT_CLEAR);
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_CLK_PORT, SL_WFX_HOST_PINOUT_SPI_CLK_PIN, gpioModePushPull, PINOUT_CLEAR);
+
+ DMADRV_Init();
+ DMADRV_AllocateChannel(&tx_dma_channel, NULL);
+ DMADRV_AllocateChannel(&rx_dma_channel, NULL);
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_CS_PORT, SL_WFX_HOST_PINOUT_SPI_CS_PIN, gpioModePushPull, PINOUT_SET);
+ USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+
+ return SL_STATUS_OK;
+}
+
+/***********************************************************************
+ * @fn void wfx_rsidev_init(void)
+ * @brief
+ * function called when driver rsidev intialization
+ * @param[in] None
+ * @return None
+ * **********************************************************************/
+void wfx_rsidev_init(void)
+{
+ wfx_host_gpio_init();
+}
+#endif /* _NOT_USED */
diff --git a/examples/platform/silabs/SiWx917/uart.cpp b/examples/platform/silabs/SiWx917/uart.cpp
new file mode 100644
index 0000000..76dbca2
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/uart.cpp
@@ -0,0 +1,343 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "AppConfig.h"
+#include "matter_shell.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "assert.h"
+#include "em_core.h"
+#include "em_usart.h"
+#include "sl_board_control.h"
+#include "sl_uartdrv_instances.h"
+#if (defined(EFR32MG24) || defined(MGM24))
+#include "sl_uartdrv_eusart_vcom_config.h"
+#else
+#include "sl_uartdrv_usart_vcom_config.h"
+#endif // EFR32MG24
+#include "uart.h"
+#include "uartdrv.h"
+#include <stddef.h>
+#include <string.h>
+
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+#include "sl_power_manager.h"
+#endif
+
+#if !defined(MIN)
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#endif
+
+#if (defined(EFR32MG24) || defined(MGM24))
+#define HELPER1(x) EUSART##x##_RX_IRQn
+#else
+#define HELPER1(x) USART##x##_RX_IRQn
+#endif
+
+#define HELPER2(x) HELPER1(x)
+
+#if (defined(EFR32MG24) || defined(MGM24))
+#define HELPER3(x) EUSART##x##_RX_IRQHandler
+#else
+#define HELPER3(x) USART##x##_RX_IRQHandler
+#endif
+
+#define HELPER4(x) HELPER3(x)
+
+// On MG24 boards VCOM runs on the EUSART device, MG12 uses the UART device
+#if (defined(EFR32MG24) || defined(MGM24))
+#define USART_IRQ HELPER2(SL_UARTDRV_EUSART_VCOM_PERIPHERAL_NO)
+#define USART_IRQHandler HELPER4(SL_UARTDRV_EUSART_VCOM_PERIPHERAL_NO)
+#define vcom_handle sl_uartdrv_eusart_vcom_handle
+#else
+#define USART_IRQ HELPER2(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
+#define USART_IRQHandler HELPER4(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
+#define vcom_handle sl_uartdrv_usart_vcom_handle
+#endif // EFR32MG24
+
+typedef struct
+{
+ // The data buffer
+ uint8_t * pBuffer;
+ // The offset of the first item written to the list.
+ volatile uint16_t Head;
+ // The offset of the next item to be written to the list.
+ volatile uint16_t Tail;
+ // Maxium size of data that can be hold in buffer before overwriting
+ uint16_t MaxSize;
+} Fifo_t;
+
+#define UART_CONSOLE_ERR -1 // Negative value in case of UART Console action failed. Triggers a failure for PW_RPC
+#define MAX_BUFFER_SIZE 256
+#define MAX_DMA_BUFFER_SIZE (MAX_BUFFER_SIZE / 2)
+// In order to reduce the probability of data loss during the dmaFull callback handler we use
+// two duplicate receive buffers so we can always have one "active" receive queue.
+static uint8_t sRxDmaBuffer[MAX_DMA_BUFFER_SIZE];
+static uint8_t sRxDmaBuffer2[MAX_DMA_BUFFER_SIZE];
+static uint16_t lastCount; // Nb of bytes already processed from the active dmaBuffer
+
+// Rx buffer for the receive Fifo
+static uint8_t sRxFifoBuffer[MAX_BUFFER_SIZE];
+static Fifo_t sReceiveFifo;
+
+static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, uint8_t * data, UARTDRV_Count_t transferCount);
+
+static bool InitFifo(Fifo_t * fifo, uint8_t * pDataBuffer, uint16_t bufferSize)
+{
+ if (fifo == NULL || pDataBuffer == NULL)
+ {
+ return false;
+ }
+
+ fifo->pBuffer = pDataBuffer;
+ fifo->MaxSize = bufferSize;
+ fifo->Tail = fifo->Head = 0;
+
+ return true;
+}
+
+/*
+ * @brief Get the amount of unprocessed bytes in the fifo buffer
+ * @param Ptr to the fifo
+ * @return Nb of "unread" bytes available in the fifo
+ */
+static uint16_t AvailableDataCount(Fifo_t * fifo)
+{
+ uint16_t size = 0;
+
+ // if equal there is no data return 0 directly
+ if (fifo->Tail != fifo->Head)
+ {
+ // determine if a wrap around occurred to get the right data size available.
+ size = (fifo->Tail < fifo->Head) ? (fifo->MaxSize - fifo->Head + fifo->Tail) : (fifo->Tail - fifo->Head);
+ }
+
+ return size;
+}
+
+/*
+ * @brief Get the available space in the fifo buffer to insert new data
+ * @param Ptr to the fifo
+ * @return Nb of free bytes left in te buffer
+ */
+static uint16_t RemainingSpace(Fifo_t * fifo)
+{
+ return fifo->MaxSize - AvailableDataCount(fifo);
+}
+
+/*
+ * @brief Write data in the fifo as a circular buffer
+ * @param Ptr to the fifo, ptr of the data to write, nb of bytes to write
+ */
+static void WriteToFifo(Fifo_t * fifo, uint8_t * pDataToWrite, uint16_t SizeToWrite)
+{
+ assert(fifo);
+ assert(pDataToWrite);
+ assert(SizeToWrite <= fifo->MaxSize);
+
+ // Overwrite is not allowed
+ if (RemainingSpace(fifo) >= SizeToWrite)
+ {
+ uint16_t nBytesBeforWrap = (fifo->MaxSize - fifo->Tail);
+ if (SizeToWrite > nBytesBeforWrap)
+ {
+ // The number of bytes to write is bigger than the remaining bytes
+ // in the buffer, we have to wrap around
+ memcpy(fifo->pBuffer + fifo->Tail, pDataToWrite, nBytesBeforWrap);
+ memcpy(fifo->pBuffer, pDataToWrite + nBytesBeforWrap, SizeToWrite - nBytesBeforWrap);
+ }
+ else
+ {
+ memcpy(fifo->pBuffer + fifo->Tail, pDataToWrite, SizeToWrite);
+ }
+
+ fifo->Tail = (fifo->Tail + SizeToWrite) % fifo->MaxSize; // increment tail with wraparound
+ }
+}
+
+/*
+ * @brief Write data in the fifo as a circular buffer
+ * @param Ptr to the fifo, ptr to contain the data to process, nb of bytes to pull from the fifo
+ * @return Nb of bytes that were retrieved.
+ */
+static uint8_t RetrieveFromFifo(Fifo_t * fifo, uint8_t * pData, uint16_t SizeToRead)
+{
+ assert(fifo);
+ assert(pData);
+ assert(SizeToRead <= fifo->MaxSize);
+
+ uint16_t ReadSize = MIN(SizeToRead, AvailableDataCount(fifo));
+ uint16_t nBytesBeforWrap = (fifo->MaxSize - fifo->Head);
+
+ if (ReadSize > nBytesBeforWrap)
+ {
+ memcpy(pData, fifo->pBuffer + fifo->Head, nBytesBeforWrap);
+ memcpy(pData + nBytesBeforWrap, fifo->pBuffer, ReadSize - nBytesBeforWrap);
+ }
+ else
+ {
+ memcpy(pData, (fifo->pBuffer + fifo->Head), ReadSize);
+ }
+
+ fifo->Head = (fifo->Head + ReadSize) % fifo->MaxSize; // increment tail with wraparound
+
+ return ReadSize;
+}
+
+/*
+ * @brief Init the the UART for serial communication, Start DMA reception
+ * and init Fifo to handle the received data from this uart
+ *
+ * @Note This UART is used for pigweed rpc
+ */
+void uartConsoleInit(void)
+{
+ sl_board_enable_vcom();
+ // Init a fifo for the data received on the uart
+ InitFifo(&sReceiveFifo, sRxFifoBuffer, MAX_BUFFER_SIZE);
+
+ // Activate 2 dma queues to always have one active
+
+ UARTDRV_Receive(vcom_handle, sRxDmaBuffer, MAX_DMA_BUFFER_SIZE, UART_rx_callback);
+ UARTDRV_Receive(vcom_handle, sRxDmaBuffer2, MAX_DMA_BUFFER_SIZE, UART_rx_callback);
+
+ // Enable USART0/EUSART0 interrupt to wake OT task when data arrives
+ NVIC_ClearPendingIRQ(USART_IRQ);
+ NVIC_EnableIRQ(USART_IRQ);
+
+#if (defined(EFR32MG24) || defined(MGM24))
+ // Clear previous RX interrupts
+ EUSART_IntClear(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+
+ // Enable RX interrupts
+ EUSART_IntEnable(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+
+ // Enable EUSART
+ EUSART_Enable(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, eusartEnable);
+#else
+ USART_IntEnable(SL_UARTDRV_USART_VCOM_PERIPHERAL, USART_IF_RXDATAV);
+#endif // EFR32MG24
+}
+
+void USART_IRQHandler(void)
+{
+#ifdef ENABLE_CHIP_SHELL
+ chip::NotifyShellProcessFromISR();
+#endif
+#if defined(SL_WIFI)
+ /* TODO */
+#elif !defined(PW_RPC_ENABLED)
+ otSysEventSignalPending();
+#endif
+
+#if (defined(EFR32MG24) || defined(MGM24))
+ EUSART_IntClear(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+#endif
+}
+
+/*
+ * @brief Callback triggered when a UARTDRV DMA buffer is full
+ */
+static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, uint8_t * data, UARTDRV_Count_t transferCount)
+{
+ (void) transferStatus;
+
+ uint8_t writeSize = (transferCount - lastCount);
+ if (RemainingSpace(&sReceiveFifo) >= writeSize)
+ {
+ WriteToFifo(&sReceiveFifo, data + lastCount, writeSize);
+ lastCount = 0;
+ }
+
+ UARTDRV_Receive(vcom_handle, data, transferCount, UART_rx_callback);
+
+#ifdef ENABLE_CHIP_SHELL
+ chip::NotifyShellProcessFromISR();
+#endif
+#if defined(SL_WIFI)
+ /* TODO */
+#elif !defined(PW_RPC_ENABLED)
+ otSysEventSignalPending();
+#endif
+}
+
+/*
+ * @brief Read the data available from the console Uart
+ * @param Buffer that contains the data to write, number bytes to write.
+ * @return Amount of bytes written or ERROR (-1)
+ */
+int16_t uartConsoleWrite(const char * Buf, uint16_t BufLength)
+{
+ if (Buf == NULL || BufLength < 1)
+ {
+ return UART_CONSOLE_ERR;
+ }
+
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+ sl_power_manager_add_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+
+ // Use of ForceTransmit here. Transmit with DMA was causing errors with PW_RPC
+ // TODO Use DMA and find/fix what causes the issue with PW
+ if (UARTDRV_ForceTransmit(vcom_handle, (uint8_t *) Buf, BufLength) == ECODE_EMDRV_UARTDRV_OK)
+ {
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+ sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+ return BufLength;
+ }
+
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+ sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+
+ return UART_CONSOLE_ERR;
+}
+
+/*
+ * @brief Read the data available from the console Uart
+ * @param Buffer for the data to be read, number bytes to read.
+ * @return Amount of bytes that was read from the rx fifo or ERROR (-1)
+ */
+int16_t uartConsoleRead(char * Buf, uint16_t NbBytesToRead)
+{
+ uint8_t * data;
+ UARTDRV_Count_t count, remaining;
+
+ if (Buf == NULL || NbBytesToRead < 1)
+ {
+ return UART_CONSOLE_ERR;
+ }
+
+ if (NbBytesToRead > AvailableDataCount(&sReceiveFifo))
+ {
+ // Not enough data available in the fifo for the read size request
+ // If there is data available in dma buffer, get it now.
+ CORE_ATOMIC_SECTION(UARTDRV_GetReceiveStatus(vcom_handle, &data, &count, &remaining); if (count > lastCount) {
+ WriteToFifo(&sReceiveFifo, data + lastCount, count - lastCount);
+ lastCount = count;
+ })
+ }
+
+ return (int16_t) RetrieveFromFifo(&sReceiveFifo, (uint8_t *) Buf, NbBytesToRead);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/uart.h b/examples/platform/silabs/SiWx917/uart.h
new file mode 100644
index 0000000..f708030
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/uart.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void uartConsoleInit(void);
+int16_t uartConsoleWrite(const char * Buf, uint16_t BufLength);
+int16_t uartConsoleRead(char * Buf, uint16_t NbBytesToRead);
+
+// Implemented by in openthread code
+#ifndef PW_RPC_ENABLED
+extern void otPlatUartReceived(const uint8_t * aBuf, uint16_t aBufLength);
+extern void otPlatUartSendDone(void);
+extern void otSysEventSignalPending(void);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/examples/platform/silabs/SiWx917/wf200/efr_spi.c b/examples/platform/silabs/SiWx917/wf200/efr_spi.c
new file mode 100644
index 0000000..fb35093
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/efr_spi.c
@@ -0,0 +1,426 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "sl_wfx_configuration_defaults.h"
+
+#include "sl_wfx.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host_api.h"
+
+#include "dmadrv.h"
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "spidrv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+#ifdef SLEEP_ENABLED
+#include "sl_power_manager.h"
+#endif
+#include "AppConfig.h"
+
+#include "gpiointerrupt.h"
+
+#include "sl_spidrv_exp_config.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+#include "wfx_host_events.h"
+
+extern SPIDRV_Handle_t sl_spidrv_exp_handle;
+
+#define USART SL_WFX_HOST_PINOUT_SPI_PERIPHERAL
+
+StaticSemaphore_t xEfrSpiSemaBuffer;
+static SemaphoreHandle_t spi_sem;
+
+static unsigned int tx_dma_channel;
+static unsigned int rx_dma_channel;
+
+static uint32_t dummy_rx_data;
+static uint32_t dummy_tx_data;
+static bool spi_enabled = false;
+
+#if defined(EFR32MG12)
+uint8_t wirq_irq_nb = SL_WFX_HOST_PINOUT_SPI_IRQ;
+#elif defined(EFR32MG24)
+uint8_t wirq_irq_nb = SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN; // SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN;
+#endif
+
+#define PIN_OUT_SET 1
+#define PIN_OUT_CLEAR 0
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_init_bus(void)
+ * @brief
+ * Initialize SPI peripheral
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_init_bus(void)
+{
+ spi_enabled = true;
+
+ /* Assign allocated DMA channel */
+ tx_dma_channel = sl_spidrv_exp_handle->txDMACh;
+ rx_dma_channel = sl_spidrv_exp_handle->rxDMACh;
+
+ /*
+ * Route EUSART1 MOSI, MISO, and SCLK to the specified pins. CS is
+ * not controlled by EUSART so there is no write to the corresponding
+ * EUSARTROUTE register to do this.
+ */
+ MY_USART->CTRL |= (1u << _USART_CTRL_SMSDELAY_SHIFT);
+
+#if defined(EFR32MG12)
+ MY_USART->ROUTEPEN = USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_CLKPEN;
+#endif
+
+#if defined(EFR32MG24)
+ GPIO->USARTROUTE[0].ROUTEEN = GPIO_USART_ROUTEEN_RXPEN | // MISO
+ GPIO_USART_ROUTEEN_TXPEN | // MOSI
+ GPIO_USART_ROUTEEN_CLKPEN;
+#endif
+
+ spi_sem = xSemaphoreCreateBinaryStatic(&xEfrSpiSemaBuffer);
+ xSemaphoreGive(spi_sem);
+
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_deinit_bus(void)
+ * @brief
+ * De-initialize SPI peripheral and DMAs
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_deinit_bus(void)
+{
+ vSemaphoreDelete(spi_sem);
+ // Stop DMAs.
+ DMADRV_StopTransfer(rx_dma_channel);
+ DMADRV_StopTransfer(tx_dma_channel);
+ DMADRV_FreeChannel(tx_dma_channel);
+ DMADRV_FreeChannel(rx_dma_channel);
+ DMADRV_DeInit();
+ USART_Reset(MY_USART);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_spi_cs_assert()
+ * @brief
+ * Assert chip select.
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_spi_cs_assert()
+{
+ GPIO_PinOutClear(SL_SPIDRV_EXP_CS_PORT, SL_SPIDRV_EXP_CS_PIN);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_spi_cs_deassert()
+ * @brief
+ * De-Assert chip select.
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_spi_cs_deassert()
+{
+ GPIO_PinOutSet(SL_SPIDRV_EXP_CS_PORT, SL_SPIDRV_EXP_CS_PIN);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void *userParam)
+ * @brief
+ * function called when the DMA complete
+ * @param[in] channel:
+ * @param[in] sequenceNo: sequence number
+ * @param[in] userParam: user parameter
+ * @return returns true if suucessful,
+ * false otherwise
+ *****************************************************************************/
+static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void * userParam)
+{
+ (void) channel;
+ (void) sequenceNo;
+ (void) userParam;
+
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ xSemaphoreGiveFromISR(spi_sem, &xHigherPriorityTaskWoken);
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+
+ return true;
+}
+
+/****************************************************************************
+ * @fn void receiveDMA(uint8_t *buffer, uint16_t buffer_length)
+ * @brief
+ * start receive DMA
+ * @param[in] buffer:
+ * @param[in] buffer_length:
+ * @return None
+ *****************************************************************************/
+void receiveDMA(uint8_t * buffer, uint16_t buffer_length)
+{
+ // Start receive DMA.
+ DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, (void *) buffer, (void *) &(MY_USART->RXDATA), true, buffer_length,
+ dmadrvDataSize1, rx_dma_complete, NULL);
+
+ // Start transmit DMA.
+ DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) &(dummy_tx_data), false,
+ buffer_length, dmadrvDataSize1, NULL, NULL);
+}
+
+/****************************************************************************
+ * @fn void transmitDMA(uint8_t *buffer, uint16_t buffer_length)
+ * @brief
+ * start transmit DMA
+ * @param[in] buffer:
+ * @param[in] buffer_length:
+ * @return None
+ *****************************************************************************/
+void transmitDMA(uint8_t * buffer, uint16_t buffer_length)
+{
+ // Receive DMA runs only to initiate callback
+ // Start receive DMA.
+ DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, &dummy_rx_data, (void *) &(MY_USART->RXDATA), false, buffer_length,
+ dmadrvDataSize1, rx_dma_complete, NULL);
+ // Start transmit DMA.
+ DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) buffer, true, buffer_length,
+ dmadrvDataSize1, NULL, NULL);
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_t type,
+ uint8_t *header,
+ uint16_t header_length,
+ uint8_t *buffer,
+ uint16_t buffer_length)
+ * @brief
+ * WFX SPI transfer implementation
+ * @param[in] type:
+ * @param[in] header:
+ * @param[in] header_length:
+ * @param[in] buffer:
+ * @param[in] buffer_length:
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_t type, uint8_t * header, uint16_t header_length,
+ uint8_t * buffer, uint16_t buffer_length)
+{
+ sl_status_t result = SL_STATUS_FAIL;
+ const bool is_read = (type == SL_WFX_BUS_READ);
+
+ while (!(MY_USART->STATUS & USART_STATUS_TXBL))
+ {
+ }
+ MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+
+ /* header length should be greater than 0 */
+ if (header_length > 0)
+ {
+ for (uint8_t * buffer_ptr = header; header_length > 0; --header_length, ++buffer_ptr)
+ {
+ MY_USART->TXDATA = (uint32_t)(*buffer_ptr);
+
+ while (!(MY_USART->STATUS & USART_STATUS_TXC))
+ {
+ }
+ }
+ while (!(MY_USART->STATUS & USART_STATUS_TXBL))
+ {
+ }
+ }
+
+ /* buffer length should be greater than 0 */
+ if (buffer_length > 0)
+ {
+ MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+ if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE)
+ {
+ if (is_read)
+ {
+ receiveDMA(buffer, buffer_length);
+ result = SL_STATUS_OK;
+ }
+ else
+ {
+ transmitDMA(buffer, buffer_length);
+ result = SL_STATUS_OK;
+ }
+
+ if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE)
+ {
+ xSemaphoreGive(spi_sem);
+ }
+ }
+ else
+ {
+ result = SL_STATUS_TIMEOUT;
+ }
+ }
+
+ return result;
+}
+
+/****************************************************************************
+ * @fn void sl_wfx_host_start_platform_interrupt(void)
+ * @brief
+ * Enable WFX interrupt
+ * @param[in] none
+ * @return None
+ *****************************************************************************/
+void sl_wfx_host_start_platform_interrupt(void)
+{
+ // Enable (and clear) the bus interrupt
+ GPIO_ExtIntConfig(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, wirq_irq_nb, true, false, true);
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_disable_platform_interrupt(void)
+ * @brief
+ * Disable WFX interrupt
+ * @param[in] None
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_disable_platform_interrupt(void)
+{
+ GPIO_IntDisable(1 << wirq_irq_nb);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_enable_platform_interrupt(void)
+ * @brief
+ * enable the platform interrupt
+ * @param[in] None
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_enable_platform_interrupt(void)
+{
+ GPIO_IntEnable(1 << wirq_irq_nb);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_enable_spi(void)
+ * @brief
+ * enable spi
+ * @param[in] None
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_enable_spi(void)
+{
+ if (spi_enabled == false)
+ {
+#ifdef SLEEP_ENABLED
+ // Prevent the host to use lower EM than EM1
+ sl_power_manager_add_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+ spi_enabled = true;
+ }
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_disable_spi(void)
+ * @brief
+ * disable spi
+ * @param[in] None
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_disable_spi(void)
+{
+ if (spi_enabled == true)
+ {
+ spi_enabled = false;
+#ifdef SLEEP_ENABLED
+ // Allow the host to use the lowest allowed EM
+ sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+ }
+ return SL_STATUS_OK;
+}
+
+/*
+ * IRQ for SPI callback
+ * Clear the Interrupt and wake up the task that
+ * handles the actions of the interrupt (typically - wfx_bus_task ())
+ */
+static void sl_wfx_spi_wakeup_irq_callback(uint8_t irqNumber)
+{
+ BaseType_t bus_task_woken;
+ uint32_t interrupt_mask;
+
+ if (irqNumber != wirq_irq_nb)
+ return;
+ // Get and clear all pending GPIO interrupts
+ interrupt_mask = GPIO_IntGet();
+ GPIO_IntClear(interrupt_mask);
+ bus_task_woken = pdFALSE;
+ xSemaphoreGiveFromISR(wfx_wakeup_sem, &bus_task_woken);
+ vTaskNotifyGiveFromISR(wfx_bus_task_handle, &bus_task_woken);
+ portYIELD_FROM_ISR(bus_task_woken);
+}
+
+/****************************************************************************
+ * Init some actions pins to the WF-200 expansion board
+ *****************************************************************************/
+void sl_wfx_host_gpio_init(void)
+{
+ SILABS_LOG("WIFI: GPIO Init:IRQ=%d", wirq_irq_nb);
+ // Enable GPIO clock.
+ CMU_ClockEnable(cmuClock_GPIO, true);
+
+ // Configure WF200 reset pin.
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN, gpioModePushPull, 0);
+ // Configure WF200 WUP pin.
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN, gpioModePushPull, 0);
+
+ // GPIO used as IRQ.
+ GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, gpioModeInputPull, 0);
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+
+ // Set up interrupt based callback function - trigger on both edges.
+ GPIOINT_Init();
+ GPIO_ExtIntConfig(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, wirq_irq_nb, true, false,
+ false); /* Don't enable it */
+
+ GPIOINT_CallbackRegister(wirq_irq_nb, sl_wfx_spi_wakeup_irq_callback);
+
+ // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!)
+ NVIC_ClearPendingIRQ(1 << wirq_irq_nb);
+ NVIC_SetPriority(GPIO_EVEN_IRQn, 5);
+ NVIC_SetPriority(GPIO_ODD_IRQn, 5);
+}
diff --git a/examples/platform/silabs/SiWx917/wf200/host_if.cpp b/examples/platform/silabs/SiWx917/wf200/host_if.cpp
new file mode 100644
index 0000000..26bd788
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/host_if.cpp
@@ -0,0 +1,1270 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Includes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+
+#include "wifi_config.h"
+
+#include "AppConfig.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+#include "wfx_host_events.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "dhcp_client.h"
+#include "ethernetif.h"
+#include <platform/CHIPDeviceLayer.h>
+
+using namespace ::chip;
+using namespace ::chip::DeviceLayer;
+
+/* wfxRsi Task will use as its stack */
+StackType_t wfxEventTaskStack[1024] = { 0 };
+
+/* Structure that will hold the TCB of the wfxRsi Task being created. */
+StaticTask_t wfxEventTaskBuffer;
+
+/* Declare a variable to hold the data associated with the created event group. */
+StaticEventGroup_t wfxEventGroup;
+
+EventGroupHandle_t sl_wfx_event_group;
+TaskHandle_t wfx_events_task_handle;
+static sl_wfx_mac_address_t ap_mac;
+static uint32_t sta_ip;
+static wfx_wifi_scan_result_t ap_info;
+
+// Set Scan Parameters
+#define ACTIVE_CHANNEL_TIME 110
+#define PASSIVE_CHANNEL_TIME 0
+#define NUM_PROBE_REQUEST 2
+
+// wfx_fmac_driver context
+sl_wfx_context_t wifiContext;
+static uint8_t wifi_extra;
+
+/*****************************************************************************
+ * macros
+ ******************************************************************************/
+#define WE_ST_STARTED 1
+#define WE_ST_STA_CONN 2
+#define WE_ST_HW_STARTED 4
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+// Connection parameters
+char softap_ssid[32] = SOFTAP_SSID_DEFAULT;
+char softap_passkey[64] = SOFTAP_PASSKEY_DEFAULT;
+sl_wfx_security_mode_t softap_security = SOFTAP_SECURITY_DEFAULT;
+uint8_t softap_channel = SOFTAP_CHANNEL_DEFAULT;
+#endif
+
+/* station network interface structures */
+struct netif * sta_netif;
+wfx_wifi_provision_t wifi_provision;
+sl_wfx_get_counters_cnf_t * counters;
+sl_wfx_get_counters_cnf_t * Tempcounters;
+#define PUT_COUNTER(name) SILABS_LOG("%-24s %lu\r\n", #name, (unsigned long) counters->body.count_##name);
+
+bool hasNotifiedIPV6 = false;
+bool hasNotifiedIPV4 = false;
+bool hasNotifiedWifiConnectivity = false;
+static uint8_t retryJoin = 0;
+bool retryInProgress = false;
+
+#ifdef SL_WFX_CONFIG_SCAN
+static struct scan_result_holder
+{
+ struct scan_result_holder * next;
+ wfx_wifi_scan_result scan;
+} * scan_save;
+static uint8_t scan_count = 0;
+static void (*scan_cb)(wfx_wifi_scan_result_t *); /* user-callback - when scan is done */
+static char * scan_ssid; /* Which one are we scanning for */
+static void sl_wfx_scan_result_callback(sl_wfx_scan_result_ind_body_t * scan_result);
+static void sl_wfx_scan_complete_callback(uint32_t status);
+#endif /* SL_WFX_CONFIG_SCAN */
+
+static void wfx_events_task(void * p_arg);
+
+/* WF200 host callbacks */
+static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication_body);
+static void sl_wfx_disconnect_callback(uint8_t * mac, uint16_t reason);
+static void sl_wfx_generic_status_callback(sl_wfx_generic_ind_t * frame);
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+static void sl_wfx_start_ap_callback(uint32_t status);
+static void sl_wfx_stop_ap_callback(void);
+static void sl_wfx_client_connected_callback(uint8_t * mac);
+static void sl_wfx_ap_client_disconnected_callback(uint32_t status, uint8_t * mac);
+static void sl_wfx_ap_client_rejected_callback(uint32_t status, uint8_t * mac);
+#endif
+
+extern uint32_t gOverrunCount;
+
+/***************************************************************************
+ * @brief
+ * Creates WFX events processing task.
+ ******************************************************************************/
+static void wfx_events_task_start()
+{
+ /* create an event group to track Wi-Fi events */
+ sl_wfx_event_group = xEventGroupCreateStatic(&wfxEventGroup);
+
+ wfx_events_task_handle = xTaskCreateStatic(wfx_events_task, "wfx_events", WLAN_TASK_STACK_SIZE, NULL, WLAN_TASK_PRIORITY,
+ wfxEventTaskStack, &wfxEventTaskBuffer);
+ if (NULL == wfx_events_task_handle)
+ {
+ SILABS_LOG("Failed to create WFX wfx_events");
+ }
+}
+
+/****************************************************************************
+ * @brief
+ * Called when the driver needs to post an event
+ * @param[in] event_payload:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload)
+{
+ switch (event_payload->header.id)
+ {
+ /******** INDICATION ********/
+ case SL_WFX_STARTUP_IND_ID: {
+ SILABS_LOG("WFX Startup Completed\r\n");
+ PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, event_payload);
+ break;
+ }
+ case SL_WFX_CONNECT_IND_ID: {
+ sl_wfx_connect_ind_t * connect_indication = (sl_wfx_connect_ind_t *) event_payload;
+ sl_wfx_connect_callback(connect_indication->body);
+ break;
+ }
+ case SL_WFX_DISCONNECT_IND_ID: {
+ sl_wfx_disconnect_ind_t * disconnect_indication = (sl_wfx_disconnect_ind_t *) event_payload;
+ sl_wfx_disconnect_callback(disconnect_indication->body.mac, disconnect_indication->body.reason);
+ break;
+ }
+ case SL_WFX_RECEIVED_IND_ID: {
+ sl_wfx_received_ind_t * ethernet_frame = (sl_wfx_received_ind_t *) event_payload;
+ if (ethernet_frame->body.frame_type == ETH_FRAME)
+ {
+ sl_wfx_host_received_frame_callback(ethernet_frame);
+ }
+ break;
+ }
+#ifdef SL_WFX_CONFIG_SCAN
+ case SL_WFX_SCAN_RESULT_IND_ID: {
+ sl_wfx_scan_result_ind_t * scan_result = (sl_wfx_scan_result_ind_t *) event_payload;
+ sl_wfx_scan_result_callback(&scan_result->body);
+ break;
+ }
+ case SL_WFX_SCAN_COMPLETE_IND_ID: {
+ sl_wfx_scan_complete_ind_t * scan_complete = (sl_wfx_scan_complete_ind_t *) event_payload;
+ sl_wfx_scan_complete_callback(scan_complete->body.status);
+ break;
+ }
+#endif /* SL_WFX_CONFIG_SCAN */
+#ifdef SL_WFX_CONFIG_SOFTAP
+ case SL_WFX_START_AP_IND_ID: {
+ sl_wfx_start_ap_ind_t * start_ap_indication = (sl_wfx_start_ap_ind_t *) event_payload;
+ sl_wfx_start_ap_callback(start_ap_indication->body.status);
+ break;
+ }
+ case SL_WFX_STOP_AP_IND_ID: {
+ sl_wfx_stop_ap_callback();
+ break;
+ }
+ case SL_WFX_AP_CLIENT_CONNECTED_IND_ID: {
+ sl_wfx_ap_client_connected_ind_t * client_connected_indication = (sl_wfx_ap_client_connected_ind_t *) event_payload;
+ sl_wfx_client_connected_callback(client_connected_indication->body.mac);
+ break;
+ }
+ case SL_WFX_AP_CLIENT_REJECTED_IND_ID: {
+ sl_wfx_ap_client_rejected_ind_t * ap_client_rejected_indication = (sl_wfx_ap_client_rejected_ind_t *) event_payload;
+ sl_wfx_ap_client_rejected_callback(ap_client_rejected_indication->body.reason, ap_client_rejected_indication->body.mac);
+ break;
+ }
+ case SL_WFX_AP_CLIENT_DISCONNECTED_IND_ID: {
+ sl_wfx_ap_client_disconnected_ind_t * ap_client_disconnected_indication =
+ (sl_wfx_ap_client_disconnected_ind_t *) event_payload;
+ sl_wfx_ap_client_disconnected_callback(ap_client_disconnected_indication->body.reason,
+ ap_client_disconnected_indication->body.mac);
+ break;
+ }
+#endif /* SL_WFX_CONFIG_SOFTAP */
+#ifdef SL_WFX_USE_SECURE_LINK
+ case SL_WFX_SECURELINK_EXCHANGE_PUB_KEYS_IND_ID: {
+ if (host_context.waited_event_id != SL_WFX_SECURELINK_EXCHANGE_PUB_KEYS_IND_ID)
+ {
+ memcpy((void *) &sl_wfx_context->secure_link_exchange_ind, (void *) event_payload, event_payload->header.length);
+ }
+ break;
+ }
+#endif
+ case SL_WFX_GENERIC_IND_ID: {
+ sl_wfx_generic_ind_t * generic_status = (sl_wfx_generic_ind_t *) event_payload;
+ sl_wfx_generic_status_callback(generic_status);
+ break;
+ }
+ case SL_WFX_EXCEPTION_IND_ID: {
+ sl_wfx_exception_ind_t * firmware_exception = (sl_wfx_exception_ind_t *) event_payload;
+ uint8_t * exception_tmp = (uint8_t *) firmware_exception;
+ SILABS_LOG("firmware exception\r\n");
+ for (uint16_t i = 0; i < firmware_exception->header.length; i += 16)
+ {
+ SILABS_LOG("hif: %.8x:", i);
+ for (uint8_t j = 0; (j < 16) && ((i + j) < firmware_exception->header.length); j++)
+ {
+ SILABS_LOG(" %.2x", *exception_tmp);
+ exception_tmp++;
+ }
+ SILABS_LOG("\r\n");
+ }
+ break;
+ }
+ case SL_WFX_ERROR_IND_ID: {
+ sl_wfx_error_ind_t * firmware_error = (sl_wfx_error_ind_t *) event_payload;
+ uint8_t * error_tmp = (uint8_t *) firmware_error;
+ SILABS_LOG("firmware error %lu\r\n", firmware_error->body.type);
+ for (uint16_t i = 0; i < firmware_error->header.length; i += 16)
+ {
+ SILABS_LOG("hif: %.8x:", i);
+ for (uint8_t j = 0; (j < 16) && ((i + j) < firmware_error->header.length); j++)
+ {
+ SILABS_LOG(" %.2x", *error_tmp);
+ error_tmp++;
+ }
+ SILABS_LOG("\r\n");
+ }
+ break;
+ }
+ }
+
+ return SL_STATUS_OK;
+}
+
+#ifdef SL_WFX_CONFIG_SCAN
+/****************************************************************************
+ * @brief
+ * Callback for individual scan result
+ * @param[in] scan_result: Scan result of all SSID's
+ *****************************************************************************/
+static void sl_wfx_scan_result_callback(sl_wfx_scan_result_ind_body_t * scan_result)
+{
+ struct scan_result_holder * ap;
+
+ SILABS_LOG("# %2d %2d %03d %02X:%02X:%02X:%02X:%02X:%02X %s", scan_count, scan_result->channel,
+ ((int16_t)(scan_result->rcpi - 220) / 2), scan_result->mac[0], scan_result->mac[1], scan_result->mac[2],
+ scan_result->mac[3], scan_result->mac[4], scan_result->mac[5], scan_result->ssid_def.ssid);
+ /*Report one AP information*/
+ SILABS_LOG("\r\n");
+ /* don't save if filter only wants specific ssid */
+ if (scan_ssid != (char *) 0)
+ {
+ if (strcmp(scan_ssid, (char *) &scan_result->ssid_def.ssid[0]) != CMP_SUCCESS)
+ return;
+ }
+ if ((ap = (struct scan_result_holder *) pvPortMalloc(sizeof(*ap))) == (struct scan_result_holder *) 0)
+ {
+ SILABS_LOG("*ERR*Scan: No Mem");
+ }
+ else
+ {
+ ap->next = scan_save;
+ scan_save = ap;
+ /* Not checking if scan_result->ssid_length is < 33 */
+ memcpy(ap->scan.ssid, scan_result->ssid_def.ssid, scan_result->ssid_def.ssid_length);
+ ap->scan.ssid[scan_result->ssid_def.ssid_length] = 0; /* make sure about null terminate */
+ /* We do it in this order WPA3 first */
+ /* No EAP supported - Is this required */
+ if (scan_result->security_mode.wpa3)
+ {
+ ap->scan.security = WFX_SEC_WPA3;
+ }
+ else if (scan_result->security_mode.wpa2)
+ {
+ ap->scan.security = WFX_SEC_WPA2;
+ }
+ else if (scan_result->security_mode.wpa)
+ {
+ ap->scan.security = WFX_SEC_WPA;
+ }
+ else if (scan_result->security_mode.wep)
+ {
+ ap->scan.security = WFX_SEC_WEP;
+ }
+ else
+ {
+ ap->scan.security = WFX_SEC_NONE;
+ }
+ ap->scan.chan = scan_result->channel;
+ ap->scan.rssi = scan_result->rcpi;
+ memcpy(&ap->scan.bssid[0], &scan_result->mac[0], BSSID_MAX_STR_LEN);
+ scan_count++;
+ }
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for scan complete
+ * @param[in] status:Status of WLAN scan api
+ *****************************************************************************/
+/* ARGSUSED */
+static void sl_wfx_scan_complete_callback(uint32_t status)
+{
+ (void) (status);
+ /* Use scan_count value and reset it */
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_SCAN_COMPLETE);
+}
+#endif /* SL_WFX_CONFIG_SCAN */
+
+/****************************************************************************
+ * @brief
+ * Callback when station connects
+ * @param[in] mac: MAC address of device
+ * @param[in] status: Status of connect call
+ *****************************************************************************/
+static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication_body)
+{
+ uint8_t * mac = connect_indication_body.mac;
+ uint32_t status = connect_indication_body.status;
+ switch (status)
+ {
+ case WFM_STATUS_SUCCESS: {
+ SILABS_LOG("STA-Connected\r\n");
+ memcpy(&ap_mac.octet[0], mac, MAC_ADDRESS_FIRST_OCTET);
+ sl_wfx_context->state =
+ static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) | static_cast<int>(SL_WFX_STA_INTERFACE_CONNECTED));
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_CONNECT);
+ break;
+ }
+ case WFM_STATUS_NO_MATCHING_AP: {
+ SILABS_LOG("WFX Connection failed, access point not found\r\n");
+ break;
+ }
+ case WFM_STATUS_CONNECTION_ABORTED: {
+ SILABS_LOG("WFX Connection aborted\r\n");
+ break;
+ }
+ case WFM_STATUS_CONNECTION_TIMEOUT: {
+ SILABS_LOG("WFX Connection timeout\r\n");
+ break;
+ }
+ case WFM_STATUS_CONNECTION_REJECTED_BY_AP: {
+ SILABS_LOG("WFX Connection rejected by the access point\r\n");
+ break;
+ }
+ case WFM_STATUS_CONNECTION_AUTH_FAILURE: {
+ SILABS_LOG("WFX Connection authentication failure\r\n");
+ break;
+ }
+ default: {
+ SILABS_LOG("WF Connection attempt error\r\n");
+ }
+ }
+
+ if ((status != WFM_STATUS_SUCCESS) && retryJoin < MAX_JOIN_RETRIES_COUNT)
+ {
+ retryJoin += 1;
+ retryInProgress = false;
+ SILABS_LOG("WFX Retry to connect to network count: %d", retryJoin);
+ sl_wfx_context->state =
+ static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) & ~static_cast<int>(SL_WFX_STARTED));
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_RETRY_CONNECT);
+ }
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for station disconnect
+ * @param[in] mac: MAC address of device
+ * @param[in] reason: Reason code of disconnection
+ *****************************************************************************/
+static void sl_wfx_disconnect_callback(uint8_t * mac, uint16_t reason)
+{
+ (void) (mac);
+ SILABS_LOG("WFX Disconnected %d\r\n", reason);
+ sl_wfx_context->state =
+ static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) & ~static_cast<int>(SL_WFX_STA_INTERFACE_CONNECTED));
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_DISCONNECT);
+}
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+/****************************************************************************
+ * @brief
+ * Callback for AP started
+ * @param[in] status: Status of wfx start ap api
+ *****************************************************************************/
+static void sl_wfx_start_ap_callback(uint32_t status)
+{
+ if (status == AP_START_SUCCESS)
+ {
+ SILABS_LOG("AP started\r\n");
+ sl_wfx_context->state =
+ static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) | static_cast<int>(SL_WFX_AP_INTERFACE_UP));
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_START_AP);
+ }
+ else
+ {
+ SILABS_LOG("AP start failed\r\n");
+ strcpy(event_log, "AP start failed");
+ }
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for AP stopped
+ *****************************************************************************/
+static void sl_wfx_stop_ap_callback(void)
+{
+ // TODO
+ // dhcpserver_clear_stored_mac();
+ SILABS_LOG("SoftAP stopped\r\n");
+ sl_wfx_context->state =
+ static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) & ~static_cast<int>(SL_WFX_AP_INTERFACE_UP));
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_STOP_AP);
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for client connect to AP
+ * @param[in] mac: MAC address of device
+ *****************************************************************************/
+static void sl_wfx_client_connected_callback(uint8_t * mac)
+{
+ SILABS_LOG("Client connected, MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ // TODO
+ SILABS_LOG("Open a web browser and go to http://%d.%d.%d.%d\r\n", ap_ip_addr0, ap_ip_addr1, ap_ip_addr2, ap_ip_addr3);
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for client rejected from AP
+ * @param[in] status: Status of ap rejected
+ * @param[in] mac: MAC address of device
+ *****************************************************************************/
+static void sl_wfx_ap_client_rejected_callback(uint32_t status, uint8_t * mac)
+{
+ SILABS_LOG("Client rejected, reason: %d, MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", (int) status, mac[0], mac[1], mac[2], mac[3],
+ mac[4], mac[5]);
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for AP client disconnect
+ * @param[in] status: Status of ap dissconnect
+ * @param[in] mac:
+ *****************************************************************************/
+static void sl_wfx_ap_client_disconnected_callback(uint32_t status, uint8_t * mac)
+{
+ // TODO
+ SILABS_LOG("Client disconnected, reason: %d, MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", (int) status, mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+}
+#endif /* SL_WFX_CONFIG_SOFTAP */
+
+/****************************************************************************
+ * @brief
+ * Callback for generic status received
+ * @param[in] farme:
+ *****************************************************************************/
+static void sl_wfx_generic_status_callback(sl_wfx_generic_ind_t * frame)
+{
+ (void) (frame);
+ SILABS_LOG("WFX Generic status received\r\n");
+}
+
+/***************************************************************************
+ * @brief
+ * WFX events processing task.
+ * @param[in] p_arg:
+ * ******************************************************************************/
+static void wfx_events_task(void * p_arg)
+{
+ TickType_t last_dhcp_poll, now;
+ EventBits_t flags;
+ (void) p_arg;
+
+ sta_netif = wfx_get_netif(SL_WFX_STA_INTERFACE);
+ last_dhcp_poll = xTaskGetTickCount();
+ while (true)
+ {
+ flags = xEventGroupWaitBits(sl_wfx_event_group,
+ SL_WFX_CONNECT | SL_WFX_DISCONNECT
+#ifdef SL_WFX_CONFIG_SOFTAP
+ | SL_WFX_START_AP | SL_WFX_STOP_AP
+#endif /* SL_WFX_CONFIG_SOFTAP */
+#ifdef SL_WFX_CONFIG_SCAN
+ | SL_WFX_SCAN_START | SL_WFX_SCAN_COMPLETE
+#endif /* SL_WFX_CONFIG_SCAN */
+ | BITS_TO_WAIT,
+ pdTRUE, pdFALSE, pdMS_TO_TICKS(250)); /* 250 msec delay converted to ticks */
+ if (flags & SL_WFX_RETRY_CONNECT)
+ {
+ if (!retryInProgress)
+ {
+ SILABS_LOG("WFX sending the connect command");
+ wfx_connect_to_ap();
+ retryInProgress = true;
+ }
+ }
+
+ if (wifi_extra & WE_ST_STA_CONN)
+ {
+ if ((now = xTaskGetTickCount()) > (last_dhcp_poll + pdMS_TO_TICKS(250)))
+ {
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+ uint8_t dhcp_state = dhcpclient_poll(&sta_netif);
+
+ if ((dhcp_state == DHCP_ADDRESS_ASSIGNED) && !hasNotifiedIPV4)
+ {
+ wfx_dhcp_got_ipv4((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr);
+ hasNotifiedIPV4 = true;
+ if (!hasNotifiedWifiConnectivity)
+ {
+ SILABS_LOG("WIFI: Has Notified Wifi Connectivity");
+ wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac);
+ hasNotifiedWifiConnectivity = true;
+ }
+ }
+ else if (dhcp_state == DHCP_OFF)
+ {
+ wfx_ip_changed_notify(IP_STATUS_FAIL);
+ hasNotifiedIPV4 = false;
+ }
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+ if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6)
+ {
+ wfx_ipv6_notify(1);
+ hasNotifiedIPV6 = true;
+ if (!hasNotifiedWifiConnectivity)
+ {
+ wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac);
+ hasNotifiedWifiConnectivity = true;
+ }
+ }
+ last_dhcp_poll = now;
+ }
+ }
+
+ if (flags & SL_WFX_CONNECT)
+ {
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+ wfx_ip_changed_notify(IP_STATUS_FAIL);
+ hasNotifiedIPV4 = false;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+ wfx_ipv6_notify(GET_IPV6_FAIL);
+ hasNotifiedIPV6 = false;
+ hasNotifiedWifiConnectivity = false;
+ SILABS_LOG("WIFI: Connected to AP");
+ wifi_extra |= WE_ST_STA_CONN;
+ wfx_lwip_set_sta_link_up();
+#ifdef SLEEP_ENABLED
+ if (!(wfx_get_wifi_state() & SL_WFX_AP_INTERFACE_UP))
+ {
+ // Enable the power save
+ sl_wfx_set_power_mode(WFM_PM_MODE_PS, WFM_PM_POLL_UAPSD, BEACON_1);
+ sl_wfx_enable_device_power_save();
+ }
+#endif // SLEEP_ENABLED
+ }
+
+ if (flags & SL_WFX_DISCONNECT)
+ {
+
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+ wfx_ip_changed_notify(IP_STATUS_FAIL);
+ hasNotifiedIPV4 = false;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+ wfx_ipv6_notify(GET_IPV6_FAIL);
+ hasNotifiedIPV6 = false;
+ hasNotifiedWifiConnectivity = false;
+ wifi_extra &= ~WE_ST_STA_CONN;
+ wfx_lwip_set_sta_link_down();
+ }
+
+#ifdef SL_WFX_CONFIG_SCAN
+ if (flags & SL_WFX_SCAN_START)
+ {
+ /*
+ * Start the Scan
+ */
+ sl_wfx_ssid_def_t ssid, *sp;
+ uint16_t num_ssid, slen;
+ if (scan_ssid)
+ {
+ memset(&ssid, 0, sizeof(ssid));
+ slen = strlen(scan_ssid);
+ memcpy(&ssid.ssid[0], scan_ssid, slen);
+ ssid.ssid_length = slen;
+ num_ssid = 1;
+ sp = &ssid;
+ }
+ else
+ {
+ num_ssid = 0;
+ sp = (sl_wfx_ssid_def_t *) 0;
+ }
+
+ SILABS_LOG("WIFI Scan Parameter set to Active channel time %d, Passive "
+ "Channel Time: %d, Number of prob: %d",
+ ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+ (void) sl_wfx_set_scan_parameters(ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+ (void) sl_wfx_send_scan_command(WFM_SCAN_MODE_ACTIVE, CHANNEL_LIST, /* Channel list */
+ CHANNEL_COUNT, /* Scan all chans */
+ sp, num_ssid, IE_DATA, /* IE we're looking for */
+ IE_DATA_LENGTH, BSSID_SCAN);
+ }
+ if (flags & SL_WFX_SCAN_COMPLETE)
+ {
+ struct scan_result_holder *hp, *next;
+
+ SILABS_LOG("WIFI: Return %d scan results", scan_count);
+ for (hp = scan_save; hp; hp = next)
+ {
+ next = hp->next;
+ (*scan_cb)(&hp->scan);
+ vPortFree(hp);
+ }
+ (*scan_cb)((wfx_wifi_scan_result *) 0);
+ scan_save = (struct scan_result_holder *) 0;
+ scan_count = 0;
+ if (scan_ssid)
+ {
+ vPortFree(scan_ssid);
+ scan_ssid = (char *) 0;
+ }
+ /* Terminate scan */
+ scan_cb = 0;
+ }
+#endif /* SL_WFX_CONFIG_SCAN */
+ }
+}
+
+/****************************************************************************
+ * @brief
+ * Initialize the WF200 used by the two interfaces
+ *****************************************************************************/
+static sl_status_t wfx_init(void)
+{
+ /* Initialize the WF200 used by the two interfaces */
+ wfx_events_task_start();
+ sl_status_t status = sl_wfx_init(&wifiContext);
+ SILABS_LOG("FMAC Driver version %s", FMAC_DRIVER_VERSION_STRING);
+ switch (status)
+ {
+ case SL_STATUS_OK:
+ SILABS_LOG("WF200 FW ver:%d.%d.%d [MAC %02x:%02x:%02x-%02x:%02x:%02x]", wifiContext.firmware_major,
+ wifiContext.firmware_minor, wifiContext.firmware_build, wifiContext.mac_addr_0.octet[0],
+ wifiContext.mac_addr_0.octet[1], wifiContext.mac_addr_0.octet[2], wifiContext.mac_addr_0.octet[3],
+ wifiContext.mac_addr_0.octet[4], wifiContext.mac_addr_0.octet[5]);
+ SILABS_LOG("WF200 Init OK");
+
+ if (wifiContext.state == SL_WFX_STA_INTERFACE_CONNECTED)
+ {
+ sl_wfx_send_disconnect_command();
+ }
+
+ break;
+ case SL_STATUS_WIFI_INVALID_KEY:
+ SILABS_LOG("*ERR*WF200: F/W keyset invalid");
+ break;
+ case SL_STATUS_WIFI_FIRMWARE_DOWNLOAD_TIMEOUT:
+ SILABS_LOG("*ERR*WF200: F/W download timo");
+ break;
+ case SL_STATUS_TIMEOUT:
+ SILABS_LOG("*ERR*WF200: Poll for value timo");
+ break;
+ case SL_STATUS_FAIL:
+ SILABS_LOG("*ERR*WF200: Error");
+ break;
+ default:
+ SILABS_LOG("*ERR*WF200: Unknown");
+ }
+
+ return status;
+}
+
+/*****************************************************************************
+ * @brief
+ * tcp ip, wfx and lwip stack and start dhcp client.
+ * @return
+ * sl_status_t Shows init succes or error.
+ ******************************************************************************/
+static void wfx_wifi_hw_start(void)
+{
+ sl_status_t status;
+
+ if (wifi_extra & WE_ST_HW_STARTED)
+ return;
+ SILABS_LOG("STARTING WF200\n");
+ wifi_extra |= WE_ST_HW_STARTED;
+
+ sl_wfx_host_gpio_init();
+ if ((status = wfx_init()) == SL_STATUS_OK)
+ {
+ /* Initialize the LwIP stack */
+ SILABS_LOG("WF200:Start LWIP");
+ wfx_lwip_start();
+ wifiContext.state = SL_WFX_STARTED; /* Really this is a bit mask */
+ SILABS_LOG("WF200:ready..");
+ }
+ else
+ {
+ SILABS_LOG("*ERR*WF200:init failed");
+ }
+}
+
+/***********************************************************************
+ * @brief
+ * Get AP info
+ * @param[in] ap: access point information
+ * @return returns -1
+ **************************************************************************/
+int32_t wfx_get_ap_info(wfx_wifi_scan_result_t * ap)
+{
+ int32_t signal_strength;
+ SILABS_LOG("WIFI:SSID:: %s", &ap_info.ssid[0]);
+ memcpy(ap->ssid, ap_info.ssid, sizeof(ap_info.ssid));
+ SILABS_LOG("WIFI:Mac addr:: %02x:%02x:%02x:%02x:%02x:%02x", ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2],
+ ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]);
+ memcpy(ap->bssid, ap_info.bssid, sizeof(ap_info.bssid));
+ ap->security = ap_info.security;
+ SILABS_LOG("WIFI:security:: %d", ap->security);
+ ap->chan = ap_info.chan;
+ SILABS_LOG("WIFI:Channel:: to %d", ap->chan);
+
+ sl_status_t status = sl_wfx_get_signal_strength((uint32_t *) &signal_strength);
+
+ if (status == SL_STATUS_OK)
+ {
+ SILABS_LOG("status SL_STATUS_OK & signal_strength:: %d", signal_strength);
+ ap->rssi = (signal_strength - 220) / 2;
+ }
+ return status;
+}
+
+/************************************************************************
+ * @brief
+ * Get AP extra info
+ * @param[in] extra_info: access point extra information
+ * @return returns -1
+ **************************************************************************/
+int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t * extra_info)
+{
+ int32_t status;
+ status = get_all_counters();
+ if (status != SL_STATUS_OK)
+ {
+ SILABS_LOG("Failed to get the couters");
+ }
+ else
+ {
+ extra_info->beacon_lost_count = counters->body.count_miss_beacon;
+ extra_info->beacon_rx_count = counters->body.count_rx_beacon;
+ extra_info->mcast_rx_count = counters->body.count_rx_multicast_frames;
+ extra_info->mcast_tx_count = counters->body.count_tx_multicast_frames;
+ extra_info->ucast_rx_count = counters->body.count_rx_packets;
+ extra_info->ucast_tx_count = counters->body.count_tx_packets;
+ extra_info->overrun_count = gOverrunCount;
+ }
+ return status;
+}
+
+sl_status_t get_all_counters(void)
+{
+ sl_status_t result;
+ uint8_t command_id = 0x05;
+ uint16_t mib_id = 0x2035;
+ sl_wfx_mib_req_t * request = NULL;
+ uint32_t request_length = SL_WFX_ROUND_UP_EVEN(sizeof(sl_wfx_header_mib_t) + sizeof(sl_wfx_mib_req_body_t));
+
+ result =
+ sl_wfx_allocate_command_buffer((sl_wfx_generic_message_t **) &request, command_id, SL_WFX_CONTROL_BUFFER, request_length);
+
+ if (request == NULL)
+ {
+ }
+
+ request->body.mib_id = mib_id;
+ request->header.interface = 0x2;
+ request->header.encrypted = 0x0;
+
+ result = sl_wfx_send_request(command_id, (sl_wfx_generic_message_t *) request, request_length);
+ SL_WFX_ERROR_CHECK(result);
+
+ result = sl_wfx_host_wait_for_confirmation(command_id, SL_WFX_DEFAULT_REQUEST_TIMEOUT_MS, (void **) &counters);
+ SL_WFX_ERROR_CHECK(result);
+
+ SILABS_LOG("%-24s %12s \r\n", "", "Debug Counters Content");
+ SILABS_LOG("%-24s %lu\r\n", "rcpi", (unsigned long) counters->body.rcpi);
+ PUT_COUNTER(plcp_errors);
+ PUT_COUNTER(fcs_errors);
+ PUT_COUNTER(tx_packets);
+ PUT_COUNTER(rx_packets);
+ PUT_COUNTER(rx_packet_errors);
+ PUT_COUNTER(rx_decryption_failures);
+ PUT_COUNTER(rx_mic_failures);
+ PUT_COUNTER(rx_no_key_failures);
+ PUT_COUNTER(tx_multicast_frames);
+ PUT_COUNTER(tx_frames_success);
+ PUT_COUNTER(tx_frame_failures);
+ PUT_COUNTER(tx_frames_retried);
+ PUT_COUNTER(tx_frames_multi_retried);
+ PUT_COUNTER(rx_frame_duplicates);
+ PUT_COUNTER(rts_success);
+ PUT_COUNTER(rts_failures);
+ PUT_COUNTER(ack_failures);
+ PUT_COUNTER(rx_multicast_frames);
+ PUT_COUNTER(rx_frames_success);
+ PUT_COUNTER(rx_cmacicv_errors);
+ PUT_COUNTER(rx_cmac_replays);
+ PUT_COUNTER(rx_mgmt_ccmp_replays);
+ PUT_COUNTER(rx_bipmic_errors);
+ PUT_COUNTER(rx_beacon);
+ PUT_COUNTER(miss_beacon);
+
+error_handler:
+
+ if (result == SL_STATUS_TIMEOUT)
+ {
+ if (sl_wfx_context->used_buffers > 0)
+ {
+ sl_wfx_context->used_buffers--;
+ }
+ }
+ if (request != NULL)
+ {
+ sl_wfx_free_command_buffer((sl_wfx_generic_message_t *) request, command_id, SL_WFX_CONTROL_BUFFER);
+ }
+
+ return result;
+}
+
+/************************************************************************
+ * @brief
+ * reset the count
+ * @return returns -1
+ **************************************************************************/
+int32_t wfx_reset_counts()
+{
+ /* TODO */
+ return -1;
+}
+
+/*************************************************************************
+ * @brief
+ * I think that this is getting called before FreeRTOS threads are ready
+ * @return returns SL_STATUS_OK
+ **************************************************************************/
+sl_status_t wfx_wifi_start(void)
+{
+ if (wifi_extra & WE_ST_STARTED)
+ {
+ SILABS_LOG("WIFI: Already started");
+ return SL_STATUS_OK;
+ }
+ wifi_extra |= WE_ST_STARTED;
+ wfx_soft_init();
+ wfx_wifi_hw_start();
+
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi state
+ * @return returns wificonetext state
+ *****************************************************************************/
+sl_wfx_state_t wfx_get_wifi_state(void)
+{
+ return wifiContext.state;
+}
+
+/****************************************************************************
+ * @brief
+ * getnetif using interface
+ * @param[in] interface:
+ * @return returns selectedNetif
+ *****************************************************************************/
+struct netif * wfx_GetNetif(sl_wfx_interface_t interface)
+{
+ struct netif * SelectedNetif = NULL;
+ if (interface == SL_WFX_STA_INTERFACE)
+ {
+ SelectedNetif = sta_netif;
+ }
+#ifdef SL_WFX_CONFIG_SOFTAP
+ else if (interface == SL_WFX_SOFTAP_INTERFACE)
+ {
+ // no ap currently
+ }
+#endif
+ return SelectedNetif;
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi mac address using interface
+ * @param[in] interface:
+ * @return returns wificontext.mac_addr_o if successful,
+ * wificontext.mac_addr_1 otherwise
+ *****************************************************************************/
+sl_wfx_mac_address_t wfx_get_wifi_mac_addr(sl_wfx_interface_t interface)
+{
+ // return Mac address used by WFX SL_WFX_STA_INTERFACE or SL_WFX_SOFTAP_INTERFACE,
+ return (interface == SL_WFX_STA_INTERFACE) ? wifiContext.mac_addr_0 : wifiContext.mac_addr_1;
+}
+
+/****************************************************************************
+ * @brief
+ * set the wifi provision
+ * @param[in] wifiConfig: configuration of wifi
+ *****************************************************************************/
+void wfx_set_wifi_provision(wfx_wifi_provision_t * wifiConfig)
+{
+ memcpy(wifi_provision.ssid, wifiConfig->ssid, sizeof(wifiConfig->ssid));
+ memcpy(wifi_provision.passkey, wifiConfig->passkey, sizeof(wifiConfig->passkey));
+ SILABS_LOG("WIFI: Provision SSID=%s", &wifi_provision.ssid[0]);
+
+ /* Not very good - To be improved */
+ switch (wifiConfig->security)
+ {
+ case WFX_SEC_WPA:
+ wifi_provision.security = static_cast<uint8_t>(sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK);
+ break;
+ case WFX_SEC_WPA3:
+ wifi_provision.security = WFM_SECURITY_MODE_WPA3_SAE;
+ break;
+ case WFX_SEC_WPA2:
+ wifi_provision.security = static_cast<uint8_t>(sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK);
+ break;
+ case WFX_SEC_WPA_WPA2_MIXED:
+ wifi_provision.security = static_cast<uint8_t>(sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK);
+ break;
+ default:
+ wifi_provision.security = WFM_SECURITY_MODE_WPA2_PSK;
+ break;
+ }
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi provision
+ * @param[in] wifiConfig: configuration of wifi
+ * @return returns true if successful,
+ * false otherwise
+ *****************************************************************************/
+bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig)
+{
+ if (wifiConfig == NULL)
+ {
+ return false;
+ }
+ memcpy(wifiConfig, &wifi_provision, sizeof(wfx_wifi_provision_t));
+
+ return true;
+}
+
+/****************************************************************************
+ * @brief
+ * clear the wifi provision
+ * @return returns true if successful,
+ * false otherwise
+ *****************************************************************************/
+void wfx_clear_wifi_provision(void)
+{
+ memset(&wifi_provision, 0, sizeof(wifi_provision));
+}
+
+/****************************************************************************
+ * @brief
+ * driver STA provisioned
+ * @return returns true if successful,
+ * false otherwise
+ *****************************************************************************/
+bool wfx_is_sta_provisioned(void)
+{
+ return (wifi_provision.ssid[0]) ? true : false;
+}
+
+/****************************************************************************
+ * @fn sl_status_t wfx_connect_to_ap(void)
+ * @brief
+ * driver connect to ap
+ * @return returns SL_STATUS_NOT_AVAILABLE
+ *****************************************************************************/
+sl_status_t wfx_connect_to_ap(void)
+{
+ sl_status_t result;
+
+ if (wifi_provision.ssid[0] == 0)
+ {
+ return SL_STATUS_NOT_AVAILABLE;
+ }
+ SILABS_LOG("WIFI:JOIN to %s", &wifi_provision.ssid[0]);
+
+ SILABS_LOG("WIFI Scan Parameter set to Active channel time %d, Passive Channel "
+ "Time: %d, Number of prob: %d",
+ ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+ (void) sl_wfx_set_scan_parameters(ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+ result =
+ sl_wfx_send_join_command((uint8_t *) wifi_provision.ssid, strlen(wifi_provision.ssid), NULL, CHANNEL_0,
+ static_cast<sl_wfx_security_mode_t>(wifi_provision.security), PREVENT_ROAMING, DISABLE_PMF_MODE,
+ (uint8_t *) wifi_provision.passkey, strlen(wifi_provision.passkey), NULL, IE_DATA_LENGTH);
+
+ return result;
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi mac addresss
+ * @param[in] interface:
+ * @param[in] addr : address
+ *****************************************************************************/
+void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr)
+{
+ sl_wfx_mac_address_t * mac;
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+ mac = (interface == SL_WFX_SOFTAP_INTERFACE) ? &wifiContext.mac_addr_1 : &wifiContext.mac_addr_0;
+#else
+ mac = &wifiContext.mac_addr_0;
+#endif
+ *addr = *mac;
+ SILABS_LOG("WLAN:Get WiFi Mac addr %02x:%02x:%02x:%02x:%02x:%02x", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3],
+ mac->octet[4], mac->octet[5]);
+ memcpy(&ap_info.bssid[0], &mac->octet[0], 6);
+}
+
+/****************************************************************************
+ * @brief
+ * function called when driver have ipv4 address
+ * @param[in] which_if:
+ * @return returns false if successful,
+ * true otherwise
+ *****************************************************************************/
+bool wfx_have_ipv4_addr(sl_wfx_interface_t which_if)
+{
+ if (which_if == SL_WFX_STA_INTERFACE)
+ {
+ return (sta_ip == STA_IP_FAIL) ? false : true;
+ }
+ else
+ {
+ return false; /* TODO */
+ }
+}
+
+/****************************************************************************
+ * @brief
+ * function called when driver have ipv6 address
+ * @param[in] which_if:
+ * @return returns false if successful,
+ * true otherwise
+ *****************************************************************************/
+bool wfx_have_ipv6_addr(sl_wfx_interface_t which_if)
+{
+ SILABS_LOG("%s: started.", __func__);
+ bool status = false;
+ if (which_if == SL_WFX_STA_INTERFACE)
+ {
+ status = wfx_is_sta_connected();
+ }
+ else
+ {
+ status = false; /* TODO */
+ }
+ SILABS_LOG("%s: status: %d", __func__, status);
+ return status;
+}
+
+/****************************************************************************
+ * @brief
+ * Disconnect station mode from connected AP
+ * @returns Returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t wfx_sta_discon(void)
+{
+ SILABS_LOG("STA-Disconnecting");
+ int32_t status = sl_wfx_send_disconnect_command();
+ wifi_extra &= ~WE_ST_STA_CONN;
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_RETRY_CONNECT);
+ return status;
+}
+
+/****************************************************************************
+ * @brief
+ * enable the STA mode
+ * @return returns true
+ *****************************************************************************/
+bool wfx_is_sta_mode_enabled(void)
+{
+ return true; /* It always is */
+}
+
+/****************************************************************************
+ * @brief
+ * fuction called when driver is STA connected
+ * @return returns true if successful,
+ * false otherwise
+ *****************************************************************************/
+bool wfx_is_sta_connected(void)
+{
+ bool val;
+
+ val = (wifi_extra & WE_ST_STA_CONN) ? true : false;
+
+ SILABS_LOG("WLAN: STA %s connected", (val ? "IS" : "NOT"));
+
+ return val;
+}
+
+/****************************************************************************
+ * @brief
+ * It is automatically done when lwip link up
+ * @return returns true if successful,
+ * false otherwise
+ *****************************************************************************/
+void wfx_setup_ip6_link_local(sl_wfx_interface_t whichif)
+{
+ SILABS_LOG("Setup-IP6: TODO"); /* It is automatically done when lwip link up */
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi mode
+ * @return returns WIFI_MODE_NULL if successful,
+ * WIFI_MODE_STA otherwise
+ *****************************************************************************/
+wifi_mode_t wfx_get_wifi_mode()
+{
+ if (wifiContext.state & SL_WFX_STARTED)
+ return WIFI_MODE_STA;
+ return WIFI_MODE_NULL;
+}
+
+/*****************************************************************************
+ * @brief
+ * This is called from the context of AppTask
+ * For WF200 - Start WIFI here
+ * @return returns true if successful,
+ * false otherwise
+ ******************************************************************************/
+bool wfx_hw_ready(void)
+{
+ return (wifiContext.state & SL_WFX_STARTED) ? true : false;
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+/*****************************************************************************
+ * @brief
+ * function called when dhcp got ipv4
+ * @param[in] ip : internet protocol
+ ******************************************************************************/
+void wfx_dhcp_got_ipv4(uint32_t ip)
+{
+ /* Acquire the new IP address
+ */
+ sta_ip = ip;
+ wfx_ip_changed_notify(IP_STATUS_SUCCESS);
+}
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+
+/*****************************************************************************
+ * @brief
+ * function called from connectivityManager
+ ******************************************************************************/
+void wfx_enable_sta_mode(void)
+{
+ /* Nothing to do - default is that it is
+ place holder */
+}
+
+/****************************************************************************
+ * @brief
+ * driver scan start
+ * @param[in] callback: Callback from the wifi scan results
+ * @return returns true if successful,
+ * false otherwise
+ *****************************************************************************/
+#ifdef SL_WFX_CONFIG_SCAN
+bool wfx_start_scan(char * ssid, void (*callback)(wfx_wifi_scan_result_t *))
+{
+ int sz;
+
+ if (scan_cb)
+ return false; /* Already in progress */
+ if (ssid)
+ {
+ sz = strlen(ssid);
+ if ((scan_ssid = (char *) pvPortMalloc(sz + 1)) == (char *) 0)
+ {
+ return false;
+ }
+ strcpy(scan_ssid, ssid);
+ }
+ scan_cb = callback;
+ xEventGroupSetBits(sl_wfx_event_group, SL_WFX_SCAN_START);
+
+ return true;
+}
+
+/****************************************************************************
+ * @brief
+ * driver scan cancelation
+ *****************************************************************************/
+void wfx_cancel_scan(void)
+{
+ struct scan_result_holder *hp, *next;
+ /* Not possible */
+ if (!scan_cb)
+ {
+ return;
+ }
+ sl_wfx_send_stop_scan_command();
+ for (hp = scan_save; hp; hp = next)
+ {
+ next = hp->next;
+ vPortFree(hp);
+ }
+ scan_save = (struct scan_result_holder *) 0;
+ scan_count = 0;
+ if (scan_ssid)
+ {
+ vPortFree(scan_ssid);
+ scan_ssid = (char *) 0;
+ }
+ scan_cb = 0;
+}
+#endif /* SL_WFX_CONFIG_SCAN */
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_board.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_board.h
new file mode 100644
index 0000000..96ab968
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_board.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _SL_WFX_BOARD_H_
+#define _SL_WFX_BOARD_H_
+/*
+ * Pull in the right board PINS
+ */
+#if defined(EFR32MG12_BRD4161A) || defined(BRD4161A) || defined(EFR32MG12_BRD4162A) || defined(BRD4162A) || \
+ defined(EFR32MG12_BRD4163A) || defined(BRD4163A) || defined(EFR32MG12_BRD4164A) || defined(BRD4164A) || \
+ defined(EFR32MG12_BRD4170A) || defined(BRD4170A)
+#include "brd4161a.h"
+#elif defined(EFR32MG24_BRD4186C) || defined(BRD4186C) || defined(EFR32MG24_BRD4186A) || defined(BRD4186A)
+#include "brd4186c.h"
+#elif defined(EFR32MG24_BRD4187C) || defined(BRD4187C) || defined(EFR32MG24_BRD4187A) || defined(BRD4187A)
+#include "brd4187c.h"
+#else
+#error "Need SPI Pins"
+#endif /* EFR32MG12_BRD4161A */
+#endif /* _SL_WFX_BOARD_H_ */
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_configuration.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_configuration.h
new file mode 100644
index 0000000..deb468d
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_configuration.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// SL_WFX_DEFAULT_REQUEST_TIMEOUT_MS> Timeout period in milliseconds<250-10000>
+// Default: 5000
+// Timeout period in milliseconds for requests.
+#define SL_WFX_DEFAULT_REQUEST_TIMEOUT_MS (5000)
+
+// <h>WFx Secure Link configuration
+
+// SL_WFX_SLK_CURVE25519> Use crypto curves
+// Default: 1
+// If this option is enabled ECDH crypto is used, KDF otherwise.
+#define SL_WFX_SLK_CURVE25519 (1)
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_crypto.c b/examples/platform/silabs/SiWx917/wf200/sl_wfx_crypto.c
new file mode 100644
index 0000000..ddad3ec
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_crypto.c
@@ -0,0 +1,409 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef SL_WFX_USE_SECURE_LINK
+
+/* Includes */
+
+#include "sl_wfx.h"
+#include <stdio.h>
+
+#include "mbedtls/ccm.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/ecdh.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/md.h"
+#include "mbedtls/sha256.h"
+
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "semphr.h"
+#include "task.h"
+
+// Secure link MAC key location for WGM160P (in DI page in flash)
+#ifdef EFM32GG11B820F2048GM64 // WGM160PX22KGA2
+#define SL_WFX_FCCC_BASE_ADDR ((void *) 0x0fe08000ul)
+#define SL_WFX_FCCC_DI_OFFSET 0x1B0ul
+#define SL_WFX_FCCC_DI_ADDR ((void *) (SL_WFX_FCCC_BASE_ADDR + SL_WFX_FCCC_DI_OFFSET))
+#define SL_WFX_SECURE_LINK_MAC_KEY_LOCATION ((void *) (SL_WFX_FCCC_BASE_ADDR + 0x3D0))
+#endif
+/******************************************************
+ * Macros
+ ******************************************************/
+#define MAC_KEY_FAIL_BYTE 0XFF
+#define KEY_DIGEST_SIZE 92
+#define MEMCMP_FAIL 0
+#define MPI_SET 1
+#define SUCCESS_STATUS_WIFI_SECURE_LINK_EXCHANGE 0
+#define SHA224_0 0
+#define HMAC_SIZE 92
+#define MEMSET_LEN 1
+#define LABLE_LEN 24
+#define ADDRESS_LENGTH 0
+#define CCM_STATUS_SUCCESS 0
+/******************************************************
+ * Constants
+ ******************************************************/
+
+/* Semaphore to signal wfx driver available */
+extern TaskHandle_t wfx_securelink_task;
+extern SemaphoreHandle_t wfx_securelink_rx_mutex;
+
+/******************************************************
+ * Enumerations
+ ******************************************************/
+
+/******************************************************
+ * Type Definitions
+ ******************************************************/
+
+/******************************************************
+ * Structures
+ ******************************************************/
+
+/******************************************************
+ * Function Declarations
+ ******************************************************/
+
+static inline void reverse_bytes(uint8_t * src, uint8_t length);
+
+/******************************************************
+ * Variable Definitions
+ ******************************************************/
+
+#if SL_WFX_SLK_CURVE25519
+static mbedtls_ecdh_context mbedtls_host_context;
+static mbedtls_ctr_drbg_context host_drbg_context;
+#endif
+static mbedtls_entropy_context entropy;
+uint8_t temp_key_location[SL_WFX_HOST_PUB_KEY_MAC_SIZE];
+#ifdef EFM32GG11B820F2048GM64 // WGM160PX22KGA2
+static const uint8_t * const secure_link_mac_key = (uint8_t *) SL_WFX_SECURE_LINK_MAC_KEY_LOCATION;
+#else
+static const uint8_t secure_link_mac_key[SL_WFX_SECURE_LINK_MAC_KEY_LENGTH] = { 0x2B, 0x49, 0xFD, 0x66, 0xCB, 0x74, 0x6D, 0x6B,
+ 0x4F, 0xDC, 0xC3, 0x79, 0x4E, 0xC5, 0x9A, 0x86,
+ 0xE5, 0x48, 0x2A, 0x41, 0x22, 0x87, 0x8B, 0x12,
+ 0x1A, 0x7C, 0x3E, 0xEF, 0xB7, 0x04, 0x9E, 0xB3 };
+#endif
+/******************************************************
+ * Function Definitions
+ ******************************************************/
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_get_secure_link_mac_key(uint8_t *sl_mac_key)
+ * @brief
+ * Get secure link mac key
+ * @param[in] sl_mac_key:
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_secure_link_mac_key(uint8_t * sl_mac_key)
+{
+ sl_status_t result = SL_STATUS_WIFI_SECURE_LINK_MAC_KEY_ERROR;
+
+ memcpy(sl_mac_key, secure_link_mac_key, SL_WFX_SECURE_LINK_MAC_KEY_LENGTH);
+
+ for (uint8_t index = 0; index < SL_WFX_SECURE_LINK_MAC_KEY_LENGTH; ++index)
+ {
+ // Assuming 0xFF... when not written
+ if (sl_mac_key[index] != MAC_KEY_FAIL_BYTE)
+ {
+ result = SL_STATUS_OK;
+ break;
+ }
+ }
+
+ return result;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_compute_pub_key(sl_wfx_securelink_exchange_pub_keys_req_body_t *request,
+ const uint8_t *sl_mac_key)
+ * @brief
+ * compute host public key
+ * @param[in] request :
+ * @param[in] sl_mac_key :
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_compute_pub_key(sl_wfx_securelink_exchange_pub_keys_req_body_t * request, const uint8_t * sl_mac_key)
+{
+ sl_status_t status = SL_STATUS_OK;
+
+#if SL_WFX_SLK_CURVE25519
+ const char identifier[] = "ecdh";
+
+ mbedtls_ecdh_init(&mbedtls_host_context);
+ mbedtls_ctr_drbg_init(&host_drbg_context);
+ mbedtls_entropy_init(&entropy);
+ status = mbedtls_ctr_drbg_seed(&host_drbg_context, mbedtls_entropy_func, &entropy, (const unsigned char *) identifier,
+ sizeof(identifier));
+ status += mbedtls_ecp_group_load(&mbedtls_host_context.grp, MBEDTLS_ECP_DP_CURVE25519);
+ status += mbedtls_ecdh_gen_public(&mbedtls_host_context.grp, &mbedtls_host_context.d, &mbedtls_host_context.Q,
+ mbedtls_ctr_drbg_random, &host_drbg_context);
+ status += mbedtls_mpi_write_binary(&mbedtls_host_context.Q.X, request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE);
+#else
+ mbedtls_entropy_init(&entropy);
+ status = mbedtls_entropy_func(&entropy, request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE);
+#endif
+ reverse_bytes(request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE);
+ SL_WFX_ERROR_CHECK(status);
+
+ // Generate SHA512 digest of public key
+ status = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), sl_mac_key, SL_WFX_HOST_PUB_KEY_SIZE,
+ request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE, request->host_pub_key_mac);
+ SL_WFX_ERROR_CHECK(status);
+
+error_handler:
+ if (status != SL_STATUS_OK)
+ {
+ return SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+ }
+ return status;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_verify_pub_key(sl_wfx_securelink_exchange_pub_keys_ind_t *response_packet,
+ const uint8_t *sl_mac_key,
+ uint8_t *sl_host_pub_key)
+ * @brief
+ * verify host public key
+ * @param[in] response_packet:
+ * @param[in] sl_mac_key:
+ * @param[in] sl_host_pub_key:
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_verify_pub_key(sl_wfx_securelink_exchange_pub_keys_ind_t * response_packet, const uint8_t * sl_mac_key,
+ uint8_t * sl_host_pub_key)
+{
+ sl_status_t status = SL_STATUS_OK;
+ uint8_t shared_key_digest[KEY_DIGEST_SIZE];
+
+ if (xSemaphoreTake(wfx_securelink_rx_mutex, portMAX_DELAY) != pdTRUE)
+ {
+ return SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+ }
+
+ // Compute the Hash and verify the public key/hashing
+ status = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), sl_mac_key, SL_WFX_NCP_PUB_KEY_SIZE,
+ response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE, temp_key_location);
+ SL_WFX_ERROR_CHECK(status);
+
+ // Calculate session key if public key/SHA512 digest matches
+ if (memcmp(temp_key_location, response_packet->body.ncp_pub_key_mac, SL_WFX_HOST_PUB_KEY_MAC_SIZE) != MEMCMP_FAIL)
+ {
+ status = SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+ goto error_handler;
+ }
+
+#if SL_WFX_SLK_CURVE25519
+ SL_WFX_UNUSED_PARAMETER(sl_host_pub_key);
+
+ mbedtls_mpi_lset(&mbedtls_host_context.Qp.Z, MPI_SET);
+
+ // Read Ineo public key
+ reverse_bytes(response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+ mbedtls_mpi_read_binary(&mbedtls_host_context.Qp.X, response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+
+ // Calculate shared secret
+ if (mbedtls_ecdh_compute_shared(&mbedtls_host_context.grp, &mbedtls_host_context.z, &mbedtls_host_context.Qp,
+ &mbedtls_host_context.d, mbedtls_ctr_drbg_random,
+ &host_drbg_context) != SUCCESS_STATUS_WIFI_SECURE_LINK_EXCHANGE)
+ {
+ status = SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+ goto error_handler;
+ }
+
+ // Generate session key
+ mbedtls_mpi_write_binary(&mbedtls_host_context.z, temp_key_location, SL_WFX_HOST_PUB_KEY_SIZE);
+ reverse_bytes(temp_key_location, SL_WFX_HOST_PUB_KEY_SIZE);
+ mbedtls_sha256(temp_key_location, SL_WFX_HOST_PUB_KEY_SIZE, shared_key_digest, SHA224_0);
+#else
+ uint8_t hmac_input[HMAC_SIZE] = { 0 };
+ char label[LABLE_LEN] = "SecureLink!KeyDerivation";
+
+ memset((uint16_t *) &hmac_input[0], (uint16_t) sl_wfx_htole16(1), MEMSET_LEN);
+ memcpy((uint8_t *) &hmac_input[2], (uint8_t *) label, LABLE_LEN);
+ memcpy((uint8_t *) &hmac_input[26], sl_host_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+ memcpy((uint8_t *) &hmac_input[58], (uint8_t *) response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+ memset((uint16_t *) &hmac_input[90], (uint16_t) sl_wfx_htole16(128), 1);
+
+ // Generate SHA256 digest of hmac_input
+ status = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), sl_mac_key, SL_WFX_HOST_PUB_KEY_SIZE,
+ (uint8_t *) hmac_input, HMAC_SIZE, shared_key_digest);
+#endif
+
+ memcpy(sl_wfx_context->secure_link_session_key, shared_key_digest,
+ SL_WFX_SECURE_LINK_SESSION_KEY_LENGTH); // Use the lower 16 bytes of the sha256
+ sl_wfx_context->secure_link_nonce.hp_packet_count = 0;
+ sl_wfx_context->secure_link_nonce.rx_packet_count = 0;
+ sl_wfx_context->secure_link_nonce.tx_packet_count = 0;
+
+error_handler:
+ if (xSemaphoreGive(wfx_securelink_rx_mutex) != pdTRUE)
+ {
+ printf("ERROR: sl_wfx_securelink_rx_mutex. unable to post.\n");
+ }
+ return status;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_free_crypto_context(void)
+ * @brief
+ * Free host crypto context
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_free_crypto_context(void)
+{
+#if SL_WFX_SLK_CURVE25519
+ mbedtls_ecdh_free(&mbedtls_host_context);
+ mbedtls_ctr_drbg_free(&host_drbg_context);
+#endif
+ mbedtls_entropy_free(&entropy);
+
+ return SL_STATUS_OK;
+}
+
+/********************************************************************************
+ * @fn sl_status_t sl_wfx_host_decode_secure_link_data(uint8_t *buffer, uint32_t length, uint8_t *session_key)
+ * @brief
+ * Decode receive data
+ * Length excludes size of CCM tag and secure link header
+ * @param[in] buffer:
+ * @param[in] length:
+ * @param[in] session_key:
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ ********************************************************************************/
+sl_status_t sl_wfx_host_decode_secure_link_data(uint8_t * buffer, uint32_t length, uint8_t * session_key)
+{
+ mbedtls_ccm_context ccm_context;
+ sl_status_t status = SL_STATUS_SECURITY_DECRYPT_ERROR;
+ int crypto_status;
+ sl_wfx_nonce_t nonce = { 0, 0, 0 };
+
+ if (xSemaphoreTake(wfx_securelink_rx_mutex, portMAX_DELAY) != pdTRUE)
+ {
+ return SL_STATUS_FAIL;
+ }
+
+ // Nonce for decryption should have TX and HP counters 0, only use RX counter
+ nonce.rx_packet_count = sl_wfx_context->secure_link_nonce.rx_packet_count;
+
+ // Init context
+ mbedtls_ccm_init(&ccm_context);
+
+ // Set the crypto key
+ crypto_status = mbedtls_ccm_setkey(&ccm_context, MBEDTLS_CIPHER_ID_AES, session_key, SL_WFX_SECURE_LINK_SESSION_KEY_BIT_COUNT);
+ SL_WFX_ERROR_CHECK(crypto_status);
+
+ // Decrypt the data
+ if (!mbedtls_ccm_auth_decrypt(&ccm_context, length, (uint8_t *) &nonce, SL_WFX_SECURE_LINK_NONCE_SIZE_BYTES, NULL,
+ ADDRESS_LENGTH, (uint8_t *) buffer, (uint8_t *) buffer, (uint8_t *) buffer + length,
+ SL_WFX_SECURE_LINK_CCM_TAG_SIZE))
+ {
+ status = SL_STATUS_OK;
+ }
+
+error_handler:
+ mbedtls_ccm_free(&ccm_context);
+ if (xSemaphoreGive(wfx_securelink_rx_mutex) != pdTRUE)
+ {
+ printf("ERROR: sl_wfx_securelink_rx_mutex. unable to post.\n");
+ }
+ return status;
+}
+
+/*********************************************************************
+ * @fn sl_status_t sl_wfx_host_encode_secure_link_data(sl_wfx_generic_message_t *buffer,
+ uint32_t data_length,
+ uint8_t *session_key,
+ uint8_t *nonce)
+ * @brief
+ * Encode transmit data
+ * Length excludes size of CCM tag and secure link header
+ * @param[in] buffer:
+ * @param[in] data_length:
+ * @param[in] session_key:
+ * @param[in] nonce:
+ * @return returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+*************************************************************************/
+sl_status_t sl_wfx_host_encode_secure_link_data(sl_wfx_generic_message_t * buffer, uint32_t data_length, uint8_t * session_key,
+ uint8_t * nonce)
+{
+ mbedtls_ccm_context ccm_context;
+ sl_status_t status = SL_STATUS_FAIL;
+
+ mbedtls_ccm_init(&ccm_context);
+ if (mbedtls_ccm_setkey(&ccm_context, MBEDTLS_CIPHER_ID_AES, session_key, SL_WFX_SECURE_LINK_SESSION_KEY_BIT_COUNT) ==
+ CCM_STATUS_SUCCESS)
+ {
+ mbedtls_ccm_encrypt_and_tag(&ccm_context, data_length, nonce, SL_WFX_SECURE_LINK_NONCE_SIZE_BYTES, NULL, ADDRESS_LENGTH,
+ (uint8_t *) &buffer->header.id, (uint8_t *) &buffer->header.id,
+ (uint8_t *) &buffer->header.id + data_length, SL_WFX_SECURE_LINK_CCM_TAG_SIZE);
+ status = SL_STATUS_OK;
+ }
+
+ mbedtls_ccm_free(&ccm_context);
+
+ return status;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_schedule_secure_link_renegotiation(void)
+ * @brief
+ * Called when the driver needs to schedule secure link renegotiation
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_schedule_secure_link_renegotiation(void)
+{
+ // call sl_wfx_secure_link_renegotiate_session_key() as soon as it makes sense for the host to do so
+ xTaskNotifyGive(wfx_securelink_task);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn static inline void reverse_bytes(uint8_t *src, uint8_t length)
+ * @brief
+ * reverse the bytes
+ * @param[in] src: source
+ * @param[in] length:
+ * @returns None
+ *****************************************************************************/
+static inline void reverse_bytes(uint8_t * src, uint8_t length)
+{
+ uint8_t * lo = src;
+ uint8_t * hi = src + length - 1;
+ uint8_t swap;
+
+ while (lo < hi)
+ {
+ swap = *lo;
+ *lo++ = *hi;
+ *hi-- = swap;
+ }
+}
+
+/********************************************************************************************************
+ ********************************************************************************************************
+ * DEPENDENCIES & AVAIL CHECK(S)
+ ********************************************************************************************************
+ *******************************************************************************************************/
+
+#endif // SL_WFX_USE_SECURE_LINK
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_host.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_host.h
new file mode 100644
index 0000000..dc9bcd2
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_host.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "semphr.h"
+#include "sl_wfx.h"
+#include "task.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+uint8_t sl_wfx_host_get_waited_event(void);
+sl_status_t wfx_soft_init(void);
+
+#ifdef SLEEP_ENABLED
+sl_status_t sl_wfx_host_switch_to_wirq(void);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#define SL_WFX_MAX_STATIONS 8
+#define SL_WFX_MAX_SCAN_RESULTS 50
+
+typedef struct __attribute__((__packed__)) scan_result_list_s
+{
+ sl_wfx_ssid_def_t ssid_def;
+ uint8_t mac[SL_WFX_MAC_ADDR_SIZE];
+ uint16_t channel;
+ sl_wfx_security_mode_bitmask_t security_mode;
+ uint16_t rcpi;
+} scan_result_list_t;
+
+void sl_wfx_host_start_platform_interrupt(void);
+extern SemaphoreHandle_t wfx_wakeup_sem;
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_securelink_task.c b/examples/platform/silabs/SiWx917/wf200/sl_wfx_securelink_task.c
new file mode 100644
index 0000000..28ffdda
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_securelink_task.c
@@ -0,0 +1,85 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef SL_WFX_USE_SECURE_LINK
+#include "secure_link/sl_wfx_secure_link.h"
+
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "semphr.h"
+#include "task.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Securelink Task Configurations
+#define WFX_SECURELINK_TASK_PRIO 1u
+#define WFX_SECURELINK_TASK_STK_SIZE 512u
+
+TaskHandle_t secureLinkTaskHandle;
+SemaphoreHandle_t s_xSLSemaphore;
+StackType_t secureLinkStack[WFX_SECURELINK_TASK_STK_SIZE];
+StaticTask_t secureLinkTaskStruct;
+
+StaticSemaphore_t xSlMutexBuffer;
+
+/*********************************************************************
+ * @fn static void prvSecureLinkTask(void *p_arg)
+ * @brief
+ * The task that implements the Secure Link renegotiation with WFX.
+ * @param[in] p_arg:
+ * @return None
+ *************************************************************************/
+static void prvSecureLinkTask(void * p_arg)
+{
+ sl_status_t result;
+ (void) p_arg;
+
+ /* Create a mutex used for making Secure Link renegotiations atomic */
+ s_xSLSemaphore = xSemaphoreCreateMutexStatic(&xSlMutexBuffer);
+
+ for (;;)
+ {
+ /* Wait for a key renegotiation request */
+ ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+
+ result = sl_wfx_secure_link_renegotiate_session_key();
+ if (result != SL_STATUS_OK)
+ {
+ printf("session key negotiation error %lu\n", result);
+ }
+ }
+}
+
+/****************************************************************************
+ * @fn void wfx_securelink_task_start(void)
+ * @brief
+ * Creates WFX securelink key renegotiation task.
+ * @param[in] None
+ * @return None
+ ******************************************************************************/
+void wfx_securelink_task_start(void)
+{
+ secureLinkTaskHandle = xTaskCreateStatic(prvSecureLinkTask, "secureLinkTask", WFX_SECURELINK_TASK_STK_SIZE, NULL,
+ WFX_SECURELINK_TASK_PRIO, secureLinkStack, &secureLinkTaskStruct);
+ if (secureLinkTaskHandle == NULL)
+ {
+ printf("Failed to create WFX secureLinkTask");
+ }
+}
+
+#endif
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.c b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.c
new file mode 100644
index 0000000..8a00e45
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.c
@@ -0,0 +1,128 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_gpio.h"
+
+#include "sl_wfx.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "AppConfig.h"
+
+#define CHECK_VAL 0
+#define WFX_BUS_TASK_PRIORITY 2
+#define BUS_TASK_STACK_SIZE 1024
+static StackType_t busStack[BUS_TASK_STACK_SIZE];
+StaticTask_t busTaskStruct;
+TaskHandle_t wfx_bus_task_handle;
+
+wfx_frame_q_item wfx_bus_tx_frame;
+SemaphoreHandle_t wfxtask_tx_complete;
+SemaphoreHandle_t wfxtask_mutex;
+
+// Flag to indicate receive frames is currently running.
+static bool wfx_bus_rx_in_process = false;
+
+/***************************************************************************
+ * @fn bool wfx_bus_is_receive_processing(void)
+ * @brief
+ * Check receive frame status
+ * @param[in] None
+ * @return returns wfx_bus_rx_in_process
+ ******************************************************************************/
+bool wfx_bus_is_receive_processing(void)
+{
+ return wfx_bus_rx_in_process;
+}
+
+/*****************************************************************************
+ * @fn static sl_status_t receive_frames()
+ * @brief
+ * Receives frames from the WFX.
+ * @param[in] None
+ * @return returns result
+ ******************************************************************************/
+static sl_status_t receive_frames()
+{
+ sl_status_t result;
+ uint16_t control_register = 0;
+ wfx_bus_rx_in_process = true;
+ do
+ {
+ result = sl_wfx_receive_frame(&control_register);
+ SL_WFX_ERROR_CHECK(result);
+ } while ((control_register & SL_WFX_CONT_NEXT_LEN_MASK) != CHECK_VAL);
+
+error_handler:
+ wfx_bus_rx_in_process = false;
+ return result;
+}
+
+/********************************************************************************
+ * @fn static void wfx_bus_task(void *p_arg)
+ * @brief
+ * WFX bus communication task.
+ * receives frames from the Bus interface
+ * @param[in] p_arg:
+ * @return None
+ */
+static void wfx_bus_task(void * p_arg)
+{
+ SILABS_LOG("SPI: Bus Task started");
+ sl_wfx_host_start_platform_interrupt();
+ for (;;)
+ {
+ /*Wait for an interrupt from WFX*/
+ ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+
+ /*Disable the interrupt while treating frames received to avoid
+ *the case where the interrupt is set but there is no frame left to treat.*/
+ sl_wfx_host_disable_platform_interrupt();
+
+ /*Receive the frame(s) pending in WFX*/
+ receive_frames();
+
+ /*Re-enable the interrupt*/
+ sl_wfx_host_enable_platform_interrupt();
+ }
+}
+
+/***************************************************************************
+ * @fn void wfx_bus_start()
+ * @brief
+ * Creates WFX bus communication task.
+ * @param[in] None
+ * @return None
+ ******************************************************************************/
+void wfx_bus_start()
+{
+ wfx_bus_task_handle =
+ xTaskCreateStatic(wfx_bus_task, "wfxbus", BUS_TASK_STACK_SIZE, NULL, WFX_BUS_TASK_PRIORITY, busStack, &busTaskStruct);
+ if (wfx_bus_task_handle == NULL)
+ {
+ SILABS_LOG("*ERR*WFX BusTask");
+ }
+}
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.h
new file mode 100644
index 0000000..6838b9b
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#include "FreeRTOS.h"
+#include "sl_wfx_constants.h"
+#include "task.h"
+
+typedef struct
+{
+ sl_wfx_send_frame_req_t * frame;
+ uint32_t data_length;
+ sl_wfx_interface_t interface;
+ uint8_t priority;
+} wfx_frame_q_item;
+
+extern wfx_frame_q_item wfxtask_tx_frame;
+extern TaskHandle_t wfx_bus_task_handle;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * @fn void wfx_bus_start(void)
+ * @brief
+ * Start wfx bus communication task.
+ *****************************************************************************/
+void wfx_bus_start(void);
+
+/****************************************************************************
+ * @fn bool wfx_bus_is_receive_processing(void)
+ * @brief
+ * Returns status of wfx receive frames.
+ *****************************************************************************/
+bool wfx_bus_is_receive_processing(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/wf200/wf200.gni b/examples/platform/silabs/SiWx917/wf200/wf200.gni
new file mode 100644
index 0000000..358384a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/wf200.gni
@@ -0,0 +1,30 @@
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+wifi_sdk_dir = "${chip_root}/src/platform/silabs/EFR32/wifi"
+
+wf200_defs = [
+ "SL_HEAP_SIZE=24576",
+ "WF200_WIFI=1",
+ "SL_WIFI=1",
+ "SL_WFX_USE_SPI",
+ "SL_WFX_DEBUG_MASK=0x0003",
+]
+softap_defs = "SL_WFX_CONFIG_SOFTAP"
+wifi_scan_defs = "SL_WFX_CONFIG_SCAN"
+wf200_plat_incs = [
+ "${wifi_sdk_dir}/",
+ "${examples_plat_dir}/wf200",
+]
+wf200_plat_src = [
+ "${wifi_sdk_dir}/dhcp_client.cpp",
+ "${wifi_sdk_dir}/ethernetif.cpp",
+ "${wifi_sdk_dir}/lwip_netif.cpp",
+ "${wifi_sdk_dir}/wfx_notify.cpp",
+ "${examples_plat_dir}/wf200/sl_wfx_task.c",
+ "${examples_plat_dir}/wf200/wf200_init.c",
+ "${examples_plat_dir}/wf200/efr_spi.c",
+ "${examples_plat_dir}/wf200/host_if.cpp",
+]
diff --git a/examples/platform/silabs/SiWx917/wf200/wf200_init.c b/examples/platform/silabs/SiWx917/wf200/wf200_init.c
new file mode 100644
index 0000000..12973d3
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/wf200_init.c
@@ -0,0 +1,543 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Includes */
+
+#include "em_gpio.h"
+
+#include "sl_wfx.h"
+#include "sl_wfx_board.h"
+
+// File specific to each platform, it must be created for custom boards
+#include "sl_wfx_pds.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Firmware include */
+#include "sl_wfx_wf200_C0.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "AppConfig.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+#include "wfx_host_events.h"
+
+#include "sl_spidrv_instances.h"
+#include "spidrv.h"
+
+#define SL_WFX_EVENT_MAX_SIZE 512
+#define SL_WFX_EVENT_LIST_SIZE 1
+
+StaticSemaphore_t xWfxWakeupSemaBuffer;
+uint8_t sWfxEventQueueBuffer[SL_WFX_EVENT_LIST_SIZE * sizeof(uint8_t)];
+StaticQueue_t sWfxEventQueueStruct;
+QueueHandle_t wfx_event_Q = NULL;
+SemaphoreHandle_t wfx_wakeup_sem = NULL;
+SemaphoreHandle_t wfx_mutex = NULL;
+
+StaticSemaphore_t xWfxMutexBuffer;
+
+struct
+{
+ uint32_t wf200_firmware_download_progress;
+ int wf200_initialized;
+ uint8_t waited_event_id;
+ uint8_t posted_event_id;
+} host_context;
+
+#ifdef SL_WFX_USE_SDIO
+#ifdef SLEEP_ENABLED
+sl_status_t sl_wfx_host_enable_sdio(void);
+sl_status_t sl_wfx_host_disable_sdio(void);
+#endif
+#endif
+
+#ifdef SL_WFX_USE_SPI
+#ifdef SLEEP_ENABLED
+sl_status_t sl_wfx_host_enable_spi(void);
+sl_status_t sl_wfx_host_disable_spi(void);
+#endif
+#endif
+
+/****************************************************************************
+ * @fn sl_status_t wfx_soft_init(void)
+ * @brief
+ * WFX FMAC driver host interface initialization
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t wfx_soft_init(void)
+{
+ SILABS_LOG("WF200:Soft Init");
+ if ((wfx_event_Q = xQueueCreateStatic(SL_WFX_EVENT_LIST_SIZE, sizeof(uint8_t), sWfxEventQueueBuffer, &sWfxEventQueueStruct)) ==
+ NULL)
+ {
+ return SL_STATUS_FAIL;
+ }
+
+ if ((wfx_wakeup_sem = xSemaphoreCreateBinaryStatic(&xWfxWakeupSemaBuffer)) == NULL)
+ {
+ return SL_STATUS_FAIL;
+ }
+
+ if ((wfx_mutex = xSemaphoreCreateMutexStatic(&xWfxMutexBuffer)) == NULL)
+ {
+ return SL_STATUS_FAIL;
+ }
+
+ return SL_STATUS_OK;
+}
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_init(void)
+ * @brief
+ * Notify driver init function
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_init(void)
+{
+ SILABS_LOG("WFX: Host Init");
+ host_context.wf200_firmware_download_progress = 0;
+ host_context.wf200_initialized = 0;
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_get_firmware_data(const uint8_t **data, uint32_t data_size)
+ * @brief
+ * Get firmware data
+ * @param[in] data:
+ * @param[in] data_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_firmware_data(const uint8_t ** data, uint32_t data_size)
+{
+ *data = &sl_wfx_firmware[host_context.wf200_firmware_download_progress];
+ host_context.wf200_firmware_download_progress += data_size;
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_get_firmware_size(uint32_t *firmware_size)
+ * @brief
+ * Get firmware size
+ * @param[in] firmware_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ * SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_firmware_size(uint32_t * firmware_size)
+{
+ *firmware_size = sizeof(sl_wfx_firmware);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_get_pds_data(const char **pds_data, uint16_t index)
+ * @brief
+ * Get PDS data
+ * @param[in] pds_data:
+ * @param[in] index:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_pds_data(const char ** pds_data, uint16_t index)
+{
+ *pds_data = sl_wfx_pds[index];
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_get_pds_size(uint16_t *pds_size)
+ * @brief
+ * Get PDS size
+ * @param[in] pds_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_pds_size(uint16_t * pds_size)
+{
+ *pds_size = SL_WFX_ARRAY_COUNT(sl_wfx_pds);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_deinit(void)
+ * @brief
+ * Deinit host interface
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_deinit(void)
+{
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_allocate_buffer(void **buffer, sl_wfx_buffer_type_t type, uint32_t buffer_size)
+ * @brief
+ * Allocate buffer (Should allocate either Ethernet - from LWIP or Control) - TODO
+ * @param[in] buffer:
+ * @param[in] type:
+ * @param[in] buffer_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_allocate_buffer(void ** buffer, sl_wfx_buffer_type_t type, uint32_t buffer_size)
+{
+ if ((*buffer = pvPortMalloc(buffer_size)) == (void *) 0)
+ {
+ return SL_STATUS_FAIL;
+ }
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_free_buffer(void *buffer, sl_wfx_buffer_type_t type)
+ * @brief
+ * Free host buffer (CHECK LWIP buffer)
+ * @param[in] buffer:
+ * @param[in] type:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_free_buffer(void * buffer, sl_wfx_buffer_type_t type)
+{
+ vPortFree(buffer);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_hold_in_reset(void)
+ * @brief
+ * Set reset pin low
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_hold_in_reset(void)
+{
+ GPIO_PinOutClear(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN);
+ host_context.wf200_initialized = 0;
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_set_wake_up_pin(uint8_t state)
+ * @brief
+ * Set wakeup pin status
+ * @param[in] state:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_set_wake_up_pin(uint8_t state)
+{
+ CORE_DECLARE_IRQ_STATE;
+
+ CORE_ENTER_ATOMIC();
+ if (state > PINOUT_CLEAR_STATUS)
+ {
+#ifdef SLEEP_ENABLED
+#ifdef SL_WFX_USE_SDIO
+ sl_wfx_host_enable_sdio();
+#endif
+#ifdef SL_WFX_USE_SPI
+ sl_wfx_host_enable_spi();
+#endif
+#endif
+ GPIO_PinOutSet(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN);
+ }
+ else
+ {
+ GPIO_PinOutClear(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN);
+#ifdef SLEEP_ENABLED
+#ifdef SL_WFX_USE_SDIO
+ sl_wfx_host_disable_sdio();
+#endif
+#ifdef SL_WFX_USE_SPI
+ sl_wfx_host_disable_spi();
+#endif
+#endif
+ }
+ CORE_EXIT_ATOMIC();
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_reset_chip(void)
+ * @brief
+ * reset the host chip
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_reset_chip(void)
+{
+ // Pull it low for at least 1 ms to issue a reset sequence
+ GPIO_PinOutClear(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN);
+
+ // Delay for 10ms
+ vTaskDelay(pdMS_TO_TICKS(10));
+
+ // Hold pin high to get chip out of reset
+ GPIO_PinOutSet(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN);
+
+ // Delay for 3ms
+ vTaskDelay(pdMS_TO_TICKS(3));
+
+ host_context.wf200_initialized = 0;
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_wait_for_wake_up(void)
+ * @brief
+ * wait for the host wake up
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_wait_for_wake_up(void)
+{
+ xSemaphoreTake(wfx_wakeup_sem, TICKS_TO_WAIT_0);
+ xSemaphoreTake(wfx_wakeup_sem, TICKS_TO_WAIT_3 / portTICK_PERIOD_MS);
+
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_wait(uint32_t wait_time)
+ * @brief
+ * wait for the host
+ * @param[in] wait_time:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+
+sl_status_t sl_wfx_host_wait(uint32_t wait_time)
+{
+ uint32_t ticks = pdMS_TO_TICKS(wait_time);
+ vTaskDelay(ticks ? ticks : 10);
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_setup_waited_event(uint8_t event_id)
+ * @brief
+ * Called when the driver needs to setup the waited event
+ * @param[in] event_id:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+
+sl_status_t sl_wfx_host_setup_waited_event(uint8_t event_id)
+{
+ host_context.waited_event_id = event_id;
+ host_context.posted_event_id = 0;
+
+ return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn uint8_t sl_wfx_host_get_waited_event(void)
+ * @brief
+ * Called when the driver get waited event
+ * @returns returns host_context.waited_event_id
+ *****************************************************************************/
+
+uint8_t sl_wfx_host_get_waited_event(void)
+{
+ return host_context.waited_event_id;
+}
+
+/******************************************************************************
+ * @fn sl_status_t sl_wfx_host_wait_for_confirmation(uint8_t confirmation_id, uint32_t timeout, void **event_payload_out)
+ * @brief
+ * wait for the host confirmation
+ * @param[in] confirmation_id:
+ * @param[in] timeout:
+ * @param[in] event_payload_out:
+ * @returns Returns SL_STATUS_OK if successful,
+ * Timeout, SL_STATUS_TIMEOUT otherwise
+ *****************************************************************************/
+
+sl_status_t sl_wfx_host_wait_for_confirmation(uint8_t confirmation_id, uint32_t timeout, void ** event_payload_out)
+{
+ uint8_t posted_event_id;
+ for (uint32_t i = 0; i < timeout; i++)
+ {
+ /* Wait for an event posted by the function sl_wfx_host_post_event() */
+ if (xQueueReceive(wfx_event_Q, &posted_event_id, TICKS_TO_WAIT_1) == pdTRUE)
+ {
+ /* Once a message is received, check if it is the expected ID */
+ if (confirmation_id == posted_event_id)
+ {
+ /* Pass the confirmation reply and return*/
+ if (event_payload_out != NULL)
+ {
+ *event_payload_out = sl_wfx_context->event_payload_buffer;
+ }
+ return SL_STATUS_OK;
+ }
+ }
+ }
+ /* The wait for the confirmation timed out, return */
+ return SL_STATUS_TIMEOUT;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_lock(void)
+ * @brief
+ * Called when the driver needs to lock its access
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_TIMEOUT otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_lock(void)
+{
+
+ sl_status_t status = SL_STATUS_OK;
+
+ if (xSemaphoreTake(wfx_mutex, TICKS_TO_WAIT_500) != pdTRUE)
+ {
+ SILABS_LOG("*ERR*Wi-Fi driver mutex timo");
+ status = SL_STATUS_TIMEOUT;
+ }
+
+ return status;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_unlock(void)
+ * @brief
+ * Called when the driver needs to unlock its access
+ * @returns Returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_unlock(void)
+{
+ xSemaphoreGive(wfx_mutex);
+
+ return SL_STATUS_OK;
+}
+
+/******************************************************************************
+ * @fn sl_status_t sl_wfx_host_post_event(sl_wfx_generic_message_t *event_payload)
+ * @brief
+ * Called when the driver needs to post an event
+ * @param[in] event_payload:
+ * @returns Returns status
+ *****************************************************************************/
+sl_status_t sl_wfx_host_post_event(sl_wfx_generic_message_t * event_payload)
+{
+ sl_status_t status;
+
+ /* Forward the message to the application */
+ status = sl_wfx_host_process_event(event_payload);
+
+ if (host_context.waited_event_id == event_payload->header.id)
+ {
+ if (event_payload->header.length < SL_WFX_EVENT_MAX_SIZE)
+ {
+ /* Post the event in the queue */
+ memcpy(sl_wfx_context->event_payload_buffer, (void *) event_payload, event_payload->header.length);
+ host_context.posted_event_id = event_payload->header.id;
+ xQueueOverwrite(wfx_event_Q, (void *) &event_payload->header.id);
+ }
+ }
+
+ return status;
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_transmit_frame(void *frame, uint32_t frame_len)
+ * @brief
+ * Called when the driver needs to transmit a frame
+ * @param[in] frame:
+ * @param[in] frame_len:
+ * @returns returns sl_wfx_data_write(frame, frame_len)
+ *****************************************************************************/
+sl_status_t sl_wfx_host_transmit_frame(void * frame, uint32_t frame_len)
+{
+ return sl_wfx_data_write(frame, frame_len);
+}
+
+/****************************************************************************
+ * @fn sl_status_t sl_wfx_host_sleep_grant(sl_wfx_host_bus_transfer_type_t type,
+ sl_wfx_register_address_t address,
+ uint32_t length)
+ * @brief
+ * Called when the driver is considering putting the
+ * WFx in sleep mode
+ * @param[in] type:
+ * @param[in] address:
+ * @param[in] length:
+ * @returns SL_WIFI_SLEEP_GRANTED to let the WFx go to
+ *sleep, SL_WIFI_SLEEP_NOT_GRANTED otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_sleep_grant(sl_wfx_host_bus_transfer_type_t type, sl_wfx_register_address_t address, uint32_t length)
+{
+ (void) (type);
+ (void) (address);
+ (void) (length);
+
+ return SL_STATUS_WIFI_SLEEP_GRANTED;
+}
+
+#if SL_WFX_DEBUG_MASK
+/****************************************************************************
+ * @fn void sl_wfx_host_log(const char *str, ...)
+ * @brief
+ * Host debug output
+ * @param[in] str: string
+ * @return None
+ *****************************************************************************/
+void sl_wfx_host_log(const char * str, ...)
+{
+ va_list args;
+ va_start(args, str);
+ vprintf(str, args);
+ va_end(args);
+}
+#endif
+#ifndef PW_RPC_ENABLED
+/* Place holder - This is just to handle UART interrupts
+ * The "otThread tasks handles it. WiFi does not need it yet
+ * I don't care for it. I should really have the thread
+ * shut it off
+ */
+#if !CHIP_ENABLE_OPENTHREAD
+/****************************************************************************
+ * @fn void otSysEventSignalPending(void)
+ * @brief
+ * system event signal pending
+ * @param[in] None
+ * @return None
+ *****************************************************************************/
+void otSysEventSignalPending(void)
+{
+ // BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR();
+ SILABS_LOG("*ERR*UART intr - NOT Handled");
+ portYIELD_FROM_ISR(pdFALSE);
+}
+#endif /* !CHIP_ENABLE_OPENTHREAD */
+#endif /* PW_RPC_ENABLED */
diff --git a/src/platform/silabs/SiWx917/BLEManagerImpl.cpp b/src/platform/silabs/SiWx917/BLEManagerImpl.cpp
new file mode 100644
index 0000000..a76f26c
--- /dev/null
+++ b/src/platform/silabs/SiWx917/BLEManagerImpl.cpp
@@ -0,0 +1,1093 @@
+/*
+ *
+ * Copyright (c) 2020-2021 Project CHIP Authors
+ * Copyright (c) 2019 Nest Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides an implementation of the BLEManager singleton object
+ * for the Silicon Labs EFR32 platforms.
+ */
+
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include "sl_component_catalog.h"
+
+#include <platform/internal/BLEManager.h>
+
+#include "FreeRTOS.h"
+#include "rail.h"
+extern "C" {
+#include "sl_bluetooth.h"
+}
+#include "sl_bt_api.h"
+#include "sl_bt_stack_config.h"
+#include "sl_bt_stack_init.h"
+#include "timers.h"
+#include <ble/CHIPBleServiceData.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <platform/CommissionableDataProvider.h>
+#include <platform/DeviceInstanceInfoProvider.h>
+#include <sl_bt_rtos_adaptation.h>
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+#include <setup_payload/AdditionalDataPayloadGenerator.h>
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Ble;
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+namespace {
+
+#define CHIP_ADV_DATA_TYPE_FLAGS 0x01
+#define CHIP_ADV_DATA_TYPE_UUID 0x03
+#define CHIP_ADV_DATA_TYPE_NAME 0x09
+#define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
+
+#define CHIP_ADV_DATA_FLAGS 0x06
+
+#define CHIP_ADV_DATA 0
+#define CHIP_ADV_SCAN_RESPONSE_DATA 1
+#define CHIP_ADV_SHORT_UUID_LEN 2
+
+#define MAX_RESPONSE_DATA_LEN 31
+#define MAX_ADV_DATA_LEN 31
+
+// Timer Frequency used.
+#define TIMER_CLK_FREQ ((uint32_t) 32768)
+// Convert msec to timer ticks.
+#define TIMER_MS_2_TIMERTICK(ms) ((TIMER_CLK_FREQ * ms) / 1000)
+#define TIMER_S_2_TIMERTICK(s) (TIMER_CLK_FREQ * s)
+
+#define BLE_MAX_BUFFER_SIZE (3076)
+#define BLE_MAX_ADVERTISERS (1)
+#define BLE_CONFIG_MAX_PERIODIC_ADVERTISING_SYNC (0)
+#define BLE_CONFIG_MAX_SOFTWARE_TIMERS (4)
+#define BLE_CONFIG_MIN_TX_POWER (-30)
+#define BLE_CONFIG_MAX_TX_POWER (80)
+#define BLE_CONFIG_RF_PATH_GAIN_TX (0)
+#define BLE_CONFIG_RF_PATH_GAIN_RX (0)
+
+// Default Connection parameters
+#define BLE_CONFIG_MIN_INTERVAL (16) // Time = Value x 1.25 ms = 30ms
+#define BLE_CONFIG_MAX_INTERVAL (80) // Time = Value x 1.25 ms = 100ms
+#define BLE_CONFIG_LATENCY (0)
+#define BLE_CONFIG_TIMEOUT (100) // Time = Value x 10 ms = 1s
+#define BLE_CONFIG_MIN_CE_LENGTH (0) // Leave to min value
+#define BLE_CONFIG_MAX_CE_LENGTH (0xFFFF) // Leave to max value
+
+TimerHandle_t sbleAdvTimeoutTimer; // FreeRTOS sw timer.
+
+const uint8_t UUID_CHIPoBLEService[] = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x10, 0x00, 0x00, 0xF6, 0xFF, 0x00, 0x00 };
+const uint8_t ShortUUID_CHIPoBLEService[] = { 0xF6, 0xFF };
+const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
+ 0x9D, 0x11 } };
+const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
+ 0x9D, 0x12 } };
+
+} // namespace
+
+BLEManagerImpl BLEManagerImpl::sInstance;
+
+CHIP_ERROR BLEManagerImpl::_Init()
+{
+ CHIP_ERROR err;
+
+ // Initialize the CHIP BleLayer.
+ err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
+ SuccessOrExit(err);
+
+ memset(mBleConnections, 0, sizeof(mBleConnections));
+ memset(mIndConfId, kUnusedIndex, sizeof(mIndConfId));
+ mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
+
+ // Create FreeRTOS sw timer for BLE timeouts and interval change.
+ sbleAdvTimeoutTimer = xTimerCreate("BleAdvTimer", // Just a text name, not used by the RTOS kernel
+ 1, // == default timer period (mS)
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = ble obj context
+ BleAdvTimeoutHandler // timer callback handler
+ );
+
+ mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
+ mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+ PlatformMgr().ScheduleWork(DriveBLEState, 0);
+
+exit:
+ return err;
+}
+
+uint16_t BLEManagerImpl::_NumConnections(void)
+{
+ uint16_t numCons = 0;
+ for (uint16_t i = 0; i < kMaxConnections; i++)
+ {
+ if (mBleConnections[i].allocated)
+ {
+ numCons++;
+ }
+ }
+
+ return numCons;
+}
+
+CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
+
+ if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
+ {
+ mFlags.Set(Flags::kAdvertisingEnabled, val);
+ PlatformMgr().ScheduleWork(DriveBLEState, 0);
+ }
+
+exit:
+ return err;
+}
+
+CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
+{
+ switch (mode)
+ {
+ case BLEAdvertisingMode::kFastAdvertising:
+ mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+ break;
+ case BLEAdvertisingMode::kSlowAdvertising:
+ mFlags.Set(Flags::kFastAdvertisingEnabled, false);
+ break;
+ default:
+ return CHIP_ERROR_INVALID_ARGUMENT;
+ }
+ mFlags.Set(Flags::kRestartAdvertising);
+ PlatformMgr().ScheduleWork(DriveBLEState, 0);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
+{
+ if (strlen(mDeviceName) >= bufSize)
+ {
+ return CHIP_ERROR_BUFFER_TOO_SMALL;
+ }
+ strcpy(buf, mDeviceName);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
+{
+ if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
+ {
+ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+ }
+ if (deviceName != NULL && deviceName[0] != 0)
+ {
+ if (strlen(deviceName) >= kMaxDeviceNameLength)
+ {
+ return CHIP_ERROR_INVALID_ARGUMENT;
+ }
+ strcpy(mDeviceName, deviceName);
+ mFlags.Set(Flags::kDeviceNameSet);
+ mFlags.Set(Flags::kRestartAdvertising);
+ ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", mDeviceName);
+ }
+ else
+ {
+ mDeviceName[0] = 0;
+ }
+ PlatformMgr().ScheduleWork(DriveBLEState, 0);
+ return CHIP_NO_ERROR;
+}
+
+void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
+{
+ switch (event->Type)
+ {
+ case DeviceEventType::kCHIPoBLESubscribe: {
+ ChipDeviceEvent connEstEvent;
+
+ ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLESubscribe");
+ HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
+ connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
+ PlatformMgr().PostEventOrDie(&connEstEvent);
+ }
+ break;
+
+ case DeviceEventType::kCHIPoBLEUnsubscribe: {
+ ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
+ HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
+ }
+ break;
+
+ case DeviceEventType::kCHIPoBLEWriteReceived: {
+ ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived");
+ HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
+ PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
+ }
+ break;
+
+ case DeviceEventType::kCHIPoBLEConnectionError: {
+ ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
+ HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
+ }
+ break;
+
+ case DeviceEventType::kCHIPoBLEIndicateConfirm: {
+ ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
+ HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
+ }
+ break;
+
+ default:
+ ChipLogProgress(DeviceLayer, "_OnPlatformEvent default: event->Type = %d", event->Type);
+ break;
+ }
+}
+
+bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+ ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
+ return false;
+}
+
+bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+ ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
+ return false;
+}
+
+bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ sl_status_t ret;
+
+ ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
+
+ ret = sl_bt_connection_close(conId);
+ err = MapBLEError(ret);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "sl_bt_connection_close() failed: %s", ErrorStr(err));
+ }
+
+ return (err == CHIP_NO_ERROR);
+}
+
+uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
+{
+ CHIPoBLEConState * conState = const_cast<BLEManagerImpl *>(this)->GetConnectionState(conId);
+ return (conState != NULL) ? conState->mtu : 0;
+}
+
+bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+ PacketBufferHandle data)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ CHIPoBLEConState * conState = GetConnectionState(conId);
+ sl_status_t ret;
+ uint16_t cId = (UUIDsMatch(&ChipUUID_CHIPoBLEChar_RX, charId) ? gattdb_CHIPoBLEChar_Rx : gattdb_CHIPoBLEChar_Tx);
+ uint8_t timerHandle = GetTimerHandle(conId, true);
+
+ VerifyOrExit(((conState != NULL) && (conState->subscribed != 0)), err = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(timerHandle != kMaxConnections, err = CHIP_ERROR_NO_MEMORY);
+
+ // start timer for light indication confirmation. Long delay for spake2 indication
+ sl_bt_system_set_lazy_soft_timer(TIMER_S_2_TIMERTICK(6), 0, timerHandle, true);
+
+ ret = sl_bt_gatt_server_send_indication(conId, cId, (data->DataLength()), data->Start());
+ err = MapBLEError(ret);
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
+ return false;
+ }
+
+ return true;
+}
+
+bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+ PacketBufferHandle pBuf)
+{
+ ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
+ return false;
+}
+
+bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+ PacketBufferHandle pBuf)
+{
+ ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
+ return false;
+}
+
+bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
+ const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+ ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
+ return false;
+}
+
+void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
+{
+ // Nothing to do
+}
+
+CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr)
+{
+ switch (bleErr)
+ {
+ case SL_STATUS_OK:
+ return CHIP_NO_ERROR;
+ case SL_STATUS_BT_ATT_INVALID_ATT_LENGTH:
+ return CHIP_ERROR_INVALID_STRING_LENGTH;
+ case SL_STATUS_INVALID_PARAMETER:
+ return CHIP_ERROR_INVALID_ARGUMENT;
+ case SL_STATUS_INVALID_STATE:
+ return CHIP_ERROR_INCORRECT_STATE;
+ case SL_STATUS_NOT_SUPPORTED:
+ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+ default:
+ return CHIP_ERROR(ChipError::Range::kPlatform, bleErr + CHIP_DEVICE_CONFIG_SILABS_BLE_ERROR_MIN);
+ }
+}
+
+void BLEManagerImpl::DriveBLEState(void)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ // Check if BLE stack is initialized
+ VerifyOrExit(mFlags.Has(Flags::kEFRBLEStackInitialized), /* */);
+
+ // Start advertising if needed...
+ if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled) &&
+ NumConnections() < kMaxConnections)
+ {
+ // Start/re-start advertising if not already started, or if there is a pending change
+ // to the advertising configuration.
+ if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kRestartAdvertising))
+ {
+ err = StartAdvertising();
+ SuccessOrExit(err);
+ }
+ }
+
+ // Otherwise, stop advertising if it is enabled.
+ else if (mFlags.Has(Flags::kAdvertising))
+ {
+ err = StopAdvertising();
+ SuccessOrExit(err);
+ }
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
+ mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
+ }
+}
+
+CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
+{
+ sl_status_t ret;
+ ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
+ CHIP_ERROR err;
+ uint8_t responseData[MAX_RESPONSE_DATA_LEN];
+ uint8_t advData[MAX_ADV_DATA_LEN];
+ uint32_t index = 0;
+ uint32_t mDeviceNameLength = 0;
+ uint8_t mDeviceIdInfoLength = 0;
+
+ VerifyOrExit((kMaxDeviceNameLength + 1) < UINT8_MAX, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ memset(responseData, 0, MAX_RESPONSE_DATA_LEN);
+ memset(advData, 0, MAX_ADV_DATA_LEN);
+
+ err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
+ SuccessOrExit(err);
+
+ if (!mFlags.Has(Flags::kDeviceNameSet))
+ {
+ uint16_t discriminator;
+ SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator));
+
+ snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
+
+ mDeviceName[kMaxDeviceNameLength] = 0;
+ mDeviceNameLength = strlen(mDeviceName);
+
+ VerifyOrExit(mDeviceNameLength < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
+ }
+
+ mDeviceNameLength = strlen(mDeviceName); // Device Name length + length field
+ VerifyOrExit(mDeviceNameLength < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ mDeviceIdInfoLength = sizeof(mDeviceIdInfo); // Servicedatalen + length+ UUID (Short)
+ static_assert(sizeof(mDeviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t");
+ static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(mDeviceIdInfo) + 1 <= MAX_ADV_DATA_LEN, "Our buffer is not big enough");
+
+ index = 0;
+ advData[index++] = 0x02; // length
+ advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
+ advData[index++] = CHIP_ADV_DATA_FLAGS; // AD value
+ advData[index++] = static_cast<uint8_t>(mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length
+ advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type : Service Data
+ advData[index++] = ShortUUID_CHIPoBLEService[0]; // AD value
+ advData[index++] = ShortUUID_CHIPoBLEService[1];
+ memcpy(&advData[index], (void *) &mDeviceIdInfo, mDeviceIdInfoLength); // AD value
+ index += mDeviceIdInfoLength;
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+ ReturnErrorOnFailure(EncodeAdditionalDataTlv());
+#endif
+
+ if (0xff != advertising_set_handle)
+ {
+ sl_bt_advertiser_delete_set(advertising_set_handle);
+ advertising_set_handle = 0xff;
+ }
+
+ ret = sl_bt_advertiser_create_set(&advertising_set_handle);
+ if (ret != SL_STATUS_OK)
+ {
+ err = MapBLEError(ret);
+ ChipLogError(DeviceLayer, "sl_bt_advertiser_create_set() failed: %s", ErrorStr(err));
+ ExitNow();
+ }
+
+ ret = sl_bt_legacy_advertiser_set_data(advertising_set_handle, sl_bt_advertiser_advertising_data_packet, index,
+ (uint8_t *) advData);
+
+ if (ret != SL_STATUS_OK)
+ {
+ err = MapBLEError(ret);
+ ChipLogError(DeviceLayer, "sl_bt_legacy_advertiser_set_data() - Advertising Data failed: %s", ErrorStr(err));
+ ExitNow();
+ }
+
+ index = 0;
+
+ responseData[index++] = CHIP_ADV_SHORT_UUID_LEN + 1; // AD length
+ responseData[index++] = CHIP_ADV_DATA_TYPE_UUID; // AD type : uuid
+ responseData[index++] = ShortUUID_CHIPoBLEService[0]; // AD value
+ responseData[index++] = ShortUUID_CHIPoBLEService[1];
+
+ responseData[index++] = static_cast<uint8_t>(mDeviceNameLength + 1); // length
+ responseData[index++] = CHIP_ADV_DATA_TYPE_NAME; // AD type : name
+ memcpy(&responseData[index], mDeviceName, mDeviceNameLength); // AD value
+ index += mDeviceNameLength;
+
+ ret = sl_bt_legacy_advertiser_set_data(advertising_set_handle, sl_bt_advertiser_scan_response_packet, index,
+ (uint8_t *) responseData);
+
+ if (ret != SL_STATUS_OK)
+ {
+ err = MapBLEError(ret);
+ ChipLogError(DeviceLayer, "sl_bt_legacy_advertiser_set_data() - Scan Response failed: %s", ErrorStr(err));
+ ExitNow();
+ }
+
+ err = MapBLEError(ret);
+
+exit:
+ return err;
+}
+
+CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
+{
+ CHIP_ERROR err;
+ sl_status_t ret;
+ uint32_t interval_min;
+ uint32_t interval_max;
+ uint16_t numConnectionss = NumConnections();
+ uint8_t connectableAdv =
+ (numConnectionss < kMaxConnections) ? sl_bt_advertiser_connectable_scannable : sl_bt_advertiser_scannable_non_connectable;
+
+ // If already advertising, stop it, before changing values
+ if (mFlags.Has(Flags::kAdvertising))
+ {
+ sl_bt_advertiser_stop(advertising_set_handle);
+ }
+ else
+ {
+ ChipLogDetail(DeviceLayer, "Start BLE advertissement");
+ }
+
+ const uint8_t kResolvableRandomAddrType = 2; // Private resolvable random address type
+ bd_addr unusedBdAddr; // We can ignore this field when setting random address.
+ sl_bt_advertiser_set_random_address(advertising_set_handle, kResolvableRandomAddrType, unusedBdAddr, &unusedBdAddr);
+ (void) unusedBdAddr;
+
+ err = ConfigureAdvertisingData();
+ SuccessOrExit(err);
+
+ mFlags.Clear(Flags::kRestartAdvertising);
+
+ if (mFlags.Has(Flags::kFastAdvertisingEnabled))
+ {
+ interval_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
+ interval_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
+ }
+ else
+ {
+ interval_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
+ interval_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
+ }
+
+ ret = sl_bt_advertiser_set_timing(advertising_set_handle, interval_min, interval_max, 0, 0);
+ err = MapBLEError(ret);
+ SuccessOrExit(err);
+
+ sl_bt_advertiser_configure(advertising_set_handle, 1);
+ ret = sl_bt_legacy_advertiser_start(advertising_set_handle, connectableAdv);
+
+ if (SL_STATUS_OK == ret)
+ {
+ if (mFlags.Has(Flags::kFastAdvertisingEnabled))
+ {
+ StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME);
+ }
+ mFlags.Set(Flags::kAdvertising);
+ }
+
+ err = MapBLEError(ret);
+
+exit:
+ return err;
+}
+
+CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ sl_status_t ret;
+
+ if (mFlags.Has(Flags::kAdvertising))
+ {
+ mFlags.Clear(Flags::kAdvertising).Clear(Flags::kRestartAdvertising);
+ mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+
+ ret = sl_bt_advertiser_stop(advertising_set_handle);
+ sl_bt_advertiser_delete_set(advertising_set_handle);
+ advertising_set_handle = 0xff;
+ err = MapBLEError(ret);
+ SuccessOrExit(err);
+
+ CancelBleAdvTimeoutTimer();
+ }
+
+exit:
+ return err;
+}
+
+void BLEManagerImpl::UpdateMtu(volatile sl_bt_msg_t * evt)
+{
+ CHIPoBLEConState * bleConnState = GetConnectionState(evt->data.evt_gatt_mtu_exchanged.connection);
+ if (bleConnState != NULL)
+ {
+ // bleConnState->MTU is a 10-bit field inside a uint16_t. We're
+ // assigning to it from a uint16_t, and compilers warn about
+ // possibly not fitting. There's no way to suppress that warning
+ // via explicit cast; we have to disable the warning around the
+ // assignment.
+ //
+ // TODO: https://github.com/project-chip/connectedhomeip/issues/2569
+ // tracks making this safe with a check or explaining why no check
+ // is needed.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+ bleConnState->mtu = evt->data.evt_gatt_mtu_exchanged.mtu;
+#pragma GCC diagnostic pop
+ ;
+ }
+}
+
+void BLEManagerImpl::HandleBootEvent(void)
+{
+ mFlags.Set(Flags::kEFRBLEStackInitialized);
+ PlatformMgr().ScheduleWork(DriveBLEState, 0);
+}
+
+void BLEManagerImpl::HandleConnectEvent(volatile sl_bt_msg_t * evt)
+{
+ sl_bt_evt_connection_opened_t * conn_evt = (sl_bt_evt_connection_opened_t *) &(evt->data);
+ uint8_t connHandle = conn_evt->connection;
+ uint8_t bondingHandle = conn_evt->bonding;
+
+ ChipLogProgress(DeviceLayer, "Connect Event for handle : %d", connHandle);
+
+ AddConnection(connHandle, bondingHandle);
+
+ PlatformMgr().ScheduleWork(DriveBLEState, 0);
+}
+
+void BLEManagerImpl::HandleConnectionCloseEvent(volatile sl_bt_msg_t * evt)
+{
+ sl_bt_evt_connection_closed_t * conn_evt = (sl_bt_evt_connection_closed_t *) &(evt->data);
+ uint8_t connHandle = conn_evt->connection;
+
+ ChipLogProgress(DeviceLayer, "Disconnect Event for handle : %d", connHandle);
+
+ if (RemoveConnection(connHandle))
+ {
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kCHIPoBLEConnectionError;
+ event.CHIPoBLEConnectionError.ConId = connHandle;
+
+ switch (conn_evt->reason)
+ {
+ case SL_STATUS_BT_CTRL_REMOTE_USER_TERMINATED:
+ case SL_STATUS_BT_CTRL_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES:
+ case SL_STATUS_BT_CTRL_REMOTE_POWERING_OFF:
+ event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
+ break;
+
+ case SL_STATUS_BT_CTRL_CONNECTION_TERMINATED_BY_LOCAL_HOST:
+ event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
+ break;
+
+ default:
+ event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
+ break;
+ }
+
+ ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", connHandle, conn_evt->reason);
+
+ PlatformMgr().PostEventOrDie(&event);
+
+ // Arrange to re-enable connectable advertising in case it was disabled due to the
+ // maximum connection limit being reached.
+ mFlags.Set(Flags::kRestartAdvertising);
+ mFlags.Set(Flags::kFastAdvertisingEnabled);
+ PlatformMgr().ScheduleWork(DriveBLEState, 0);
+ }
+}
+
+void BLEManagerImpl::HandleWriteEvent(volatile sl_bt_msg_t * evt)
+{
+ uint16_t attribute = evt->data.evt_gatt_server_user_write_request.characteristic;
+
+ ChipLogProgress(DeviceLayer, "Char Write Req, char : %d", attribute);
+
+ if (gattdb_CHIPoBLEChar_Rx == attribute)
+ {
+ HandleRXCharWrite(evt);
+ }
+}
+
+void BLEManagerImpl::HandleTXCharCCCDWrite(volatile sl_bt_msg_t * evt)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ CHIPoBLEConState * bleConnState;
+ bool isIndicationEnabled = false;
+ ChipDeviceEvent event;
+
+ bleConnState = GetConnectionState(evt->data.evt_gatt_server_user_write_request.connection);
+ VerifyOrExit(bleConnState != NULL, err = CHIP_ERROR_NO_MEMORY);
+
+ // Determine if the client is enabling or disabling notification/indication.
+ isIndicationEnabled = (evt->data.evt_gatt_server_characteristic_status.client_config_flags == sl_bt_gatt_indication);
+
+ ChipLogProgress(DeviceLayer, "HandleTXcharCCCDWrite - Config Flags value : %d",
+ evt->data.evt_gatt_server_characteristic_status.client_config_flags);
+ ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", isIndicationEnabled ? "subscribe" : "unsubscribe");
+
+ if (isIndicationEnabled)
+ {
+ // If indications are not already enabled for the connection...
+ if (!bleConnState->subscribed)
+ {
+ bleConnState->subscribed = 1;
+ // Post an event to the CHIP queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
+ // whether the client is enabling or disabling indications.
+ {
+ event.Type = DeviceEventType::kCHIPoBLESubscribe;
+ event.CHIPoBLESubscribe.ConId = evt->data.evt_gatt_server_user_write_request.connection;
+ err = PlatformMgr().PostEvent(&event);
+ }
+ }
+ }
+ else
+ {
+ bleConnState->subscribed = 0;
+ event.Type = DeviceEventType::kCHIPoBLEUnsubscribe;
+ event.CHIPoBLESubscribe.ConId = evt->data.evt_gatt_server_user_write_request.connection;
+ err = PlatformMgr().PostEvent(&event);
+ }
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
+ }
+}
+
+void BLEManagerImpl::HandleRXCharWrite(volatile sl_bt_msg_t * evt)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ System::PacketBufferHandle buf;
+ uint16_t writeLen = evt->data.evt_gatt_server_user_write_request.value.len;
+ uint8_t * data = (uint8_t *) evt->data.evt_gatt_server_user_write_request.value.data;
+
+ // Copy the data to a packet buffer.
+ buf = System::PacketBufferHandle::NewWithData(data, writeLen, 0, 0);
+ VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
+
+ ChipLogDetail(DeviceLayer, "Write request/command received for CHIPoBLE RX characteristic (con %u, len %u)",
+ evt->data.evt_gatt_server_user_write_request.connection, buf->DataLength());
+
+ // Post an event to the CHIP queue to deliver the data into the CHIP stack.
+ {
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kCHIPoBLEWriteReceived;
+ event.CHIPoBLEWriteReceived.ConId = evt->data.evt_gatt_server_user_write_request.connection;
+ event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease();
+ err = PlatformMgr().PostEvent(&event);
+ }
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
+ }
+}
+
+void BLEManagerImpl::HandleTxConfirmationEvent(BLE_CONNECTION_OBJECT conId)
+{
+ ChipDeviceEvent event;
+ uint8_t timerHandle = sInstance.GetTimerHandle(conId, false);
+
+ ChipLogProgress(DeviceLayer, "Tx Confirmation received");
+
+ // stop indication confirmation timer
+ if (timerHandle < kMaxConnections)
+ {
+ ChipLogProgress(DeviceLayer, " stop soft timer");
+ sl_bt_system_set_lazy_soft_timer(0, 0, timerHandle, false);
+ }
+
+ event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm;
+ event.CHIPoBLEIndicateConfirm.ConId = conId;
+ PlatformMgr().PostEventOrDie(&event);
+}
+
+void BLEManagerImpl::HandleSoftTimerEvent(volatile sl_bt_msg_t * evt)
+{
+ // BLE Manager starts soft timers with timer handles less than kMaxConnections
+ // If we receive a callback for unknown timer handle ignore this.
+ if (evt->data.evt_system_soft_timer.handle < kMaxConnections)
+ {
+ ChipLogProgress(DeviceLayer, "BLEManagerImpl::HandleSoftTimerEvent CHIPOBLE_PROTOCOL_ABORT");
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kCHIPoBLEConnectionError;
+ event.CHIPoBLEConnectionError.ConId = mIndConfId[evt->data.evt_system_soft_timer.handle];
+ sInstance.mIndConfId[evt->data.evt_system_soft_timer.handle] = kUnusedIndex;
+ event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
+ PlatformMgr().PostEventOrDie(&event);
+ }
+}
+
+bool BLEManagerImpl::RemoveConnection(uint8_t connectionHandle)
+{
+ CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true);
+ bool status = false;
+
+ if (bleConnState != NULL)
+ {
+ memset(bleConnState, 0, sizeof(CHIPoBLEConState));
+ status = true;
+ }
+
+ return status;
+}
+
+void BLEManagerImpl::AddConnection(uint8_t connectionHandle, uint8_t bondingHandle)
+{
+ CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true);
+
+ if (bleConnState != NULL)
+ {
+ memset(bleConnState, 0, sizeof(CHIPoBLEConState));
+ bleConnState->allocated = 1;
+ bleConnState->connectionHandle = connectionHandle;
+ bleConnState->bondingHandle = bondingHandle;
+ }
+}
+
+BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint8_t connectionHandle, bool allocate)
+{
+ uint8_t freeIndex = kMaxConnections;
+
+ for (uint8_t i = 0; i < kMaxConnections; i++)
+ {
+ if (mBleConnections[i].allocated == 1)
+ {
+ if (mBleConnections[i].connectionHandle == connectionHandle)
+ {
+ return &mBleConnections[i];
+ }
+ }
+
+ else if (i < freeIndex)
+ {
+ freeIndex = i;
+ }
+ }
+
+ if (allocate)
+ {
+ if (freeIndex < kMaxConnections)
+ {
+ return &mBleConnections[freeIndex];
+ }
+
+ ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState");
+ }
+
+ return NULL;
+}
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+CHIP_ERROR BLEManagerImpl::EncodeAdditionalDataTlv()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ BitFlags<AdditionalDataFields> additionalDataFields;
+ AdditionalDataPayloadGeneratorParams additionalDataPayloadParams;
+
+#if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID)
+ uint8_t rotatingDeviceIdUniqueId[ConfigurationManager::kRotatingDeviceIDUniqueIDLength] = {};
+ MutableByteSpan rotatingDeviceIdUniqueIdSpan(rotatingDeviceIdUniqueId);
+
+ err = DeviceLayer::GetDeviceInstanceInfoProvider()->GetRotatingDeviceIdUniqueId(rotatingDeviceIdUniqueIdSpan);
+ SuccessOrExit(err);
+ err = ConfigurationMgr().GetLifetimeCounter(additionalDataPayloadParams.rotatingDeviceIdLifetimeCounter);
+ SuccessOrExit(err);
+ additionalDataPayloadParams.rotatingDeviceIdUniqueId = rotatingDeviceIdUniqueIdSpan;
+ additionalDataFields.Set(AdditionalDataFields::RotatingDeviceId);
+#endif /* CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) */
+
+ err = AdditionalDataPayloadGenerator().generateAdditionalDataPayload(additionalDataPayloadParams, c3AdditionalDataBufferHandle,
+ additionalDataFields);
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data (%s)", __func__);
+ }
+
+ return err;
+}
+
+void BLEManagerImpl::HandleC3ReadRequest(volatile sl_bt_msg_t * evt)
+{
+ sl_bt_evt_gatt_server_user_read_request_t * readReq =
+ (sl_bt_evt_gatt_server_user_read_request_t *) &(evt->data.evt_gatt_server_user_read_request);
+ ChipLogDetail(DeviceLayer, "Read request received for CHIPoBLEChar_C3 - opcode:%d", readReq->att_opcode);
+ sl_status_t ret = sl_bt_gatt_server_send_user_read_response(readReq->connection, readReq->characteristic, 0,
+ sInstance.c3AdditionalDataBufferHandle->DataLength(),
+ sInstance.c3AdditionalDataBufferHandle->Start(), nullptr);
+
+ if (ret != SL_STATUS_OK)
+ {
+ ChipLogDetail(DeviceLayer, "Failed to send read response, err:%ld", ret);
+ }
+}
+#endif // CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+
+uint8_t BLEManagerImpl::GetTimerHandle(uint8_t connectionHandle, bool allocate)
+{
+ uint8_t freeIndex = kMaxConnections;
+
+ for (uint8_t i = 0; i < kMaxConnections; i++)
+ {
+ if (mIndConfId[i] == connectionHandle)
+ {
+ return i;
+ }
+ else if (allocate)
+ {
+ if (i < freeIndex)
+ {
+ freeIndex = i;
+ }
+ }
+ }
+
+ if (freeIndex < kMaxConnections)
+ {
+ mIndConfId[freeIndex] = connectionHandle;
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "Failed to Save Conn Handle for indication");
+ }
+
+ return freeIndex;
+}
+
+void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer)
+{
+ if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled))
+ {
+ ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertissment");
+ BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising);
+ }
+}
+
+void BLEManagerImpl::CancelBleAdvTimeoutTimer(void)
+{
+ if (xTimerStop(sbleAdvTimeoutTimer, 0) == pdFAIL)
+ {
+ ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer");
+ }
+}
+
+void BLEManagerImpl::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs)
+{
+ if (xTimerIsTimerActive(sbleAdvTimeoutTimer))
+ {
+ CancelBleAdvTimeoutTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ticks if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sbleAdvTimeoutTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
+ {
+ ChipLogError(DeviceLayer, "Failed to start BledAdv timeout timer");
+ }
+}
+
+void BLEManagerImpl::DriveBLEState(intptr_t arg)
+{
+ sInstance.DriveBLEState();
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+
+extern "C" void sl_bt_on_event(sl_bt_msg_t * evt)
+{
+ // As this is running in a separate thread, we need to block CHIP from operating,
+ // until the events are handled.
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+
+ // handle bluetooth events
+ switch (SL_BT_MSG_ID(evt->header))
+ {
+ case sl_bt_evt_system_boot_id: {
+ ChipLogProgress(DeviceLayer, "Bluetooth stack booted: v%d.%d.%d-b%d", evt->data.evt_system_boot.major,
+ evt->data.evt_system_boot.minor, evt->data.evt_system_boot.patch, evt->data.evt_system_boot.build);
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleBootEvent();
+
+ RAIL_Version_t railVer;
+ RAIL_GetVersion(&railVer, true);
+ ChipLogProgress(DeviceLayer, "RAIL version:, v%d.%d.%d-b%d", railVer.major, railVer.minor, railVer.rev, railVer.build);
+ sl_bt_connection_set_default_parameters(BLE_CONFIG_MIN_INTERVAL, BLE_CONFIG_MAX_INTERVAL, BLE_CONFIG_LATENCY,
+ BLE_CONFIG_TIMEOUT, BLE_CONFIG_MIN_CE_LENGTH, BLE_CONFIG_MAX_CE_LENGTH);
+ }
+ break;
+
+ case sl_bt_evt_connection_opened_id: {
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleConnectEvent(evt);
+ }
+ break;
+ case sl_bt_evt_connection_parameters_id: {
+ // ChipLogProgress(DeviceLayer, "Connection parameter ID received");
+ }
+ break;
+ case sl_bt_evt_connection_phy_status_id: {
+ // ChipLogProgress(DeviceLayer, "PHY update procedure is completed");
+ }
+ break;
+ case sl_bt_evt_connection_closed_id: {
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleConnectionCloseEvent(evt);
+ }
+ break;
+
+ /* This event indicates that a remote GATT client is attempting to write a value of an
+ * attribute in to the local GATT database, where the attribute was defined in the GATT
+ * XML firmware configuration file to have type="user". */
+ case sl_bt_evt_gatt_server_attribute_value_id: {
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleWriteEvent(evt);
+ }
+ break;
+
+ case sl_bt_evt_gatt_mtu_exchanged_id: {
+ chip::DeviceLayer::Internal::BLEMgrImpl().UpdateMtu(evt);
+ }
+ break;
+
+ // confirmation of indication received from remote GATT client
+ case sl_bt_evt_gatt_server_characteristic_status_id: {
+ sl_bt_gatt_server_characteristic_status_flag_t StatusFlags;
+
+ StatusFlags = (sl_bt_gatt_server_characteristic_status_flag_t) evt->data.evt_gatt_server_characteristic_status.status_flags;
+
+ if (sl_bt_gatt_server_confirmation == StatusFlags)
+ {
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleTxConfirmationEvent(
+ evt->data.evt_gatt_server_characteristic_status.connection);
+ }
+ else if ((evt->data.evt_gatt_server_characteristic_status.characteristic == gattdb_CHIPoBLEChar_Tx) &&
+ (evt->data.evt_gatt_server_characteristic_status.status_flags == gatt_server_client_config))
+ {
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleTXCharCCCDWrite(evt);
+ }
+ }
+ break;
+
+ /* Software Timer event */
+ case sl_bt_evt_system_soft_timer_id: {
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleSoftTimerEvent(evt);
+ }
+ break;
+
+ case sl_bt_evt_gatt_server_user_read_request_id: {
+ ChipLogProgress(DeviceLayer, "GATT server user_read_request");
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+ if (evt->data.evt_gatt_server_user_read_request.characteristic == gattdb_CHIPoBLEChar_C3)
+ {
+ chip::DeviceLayer::Internal::BLEMgrImpl().HandleC3ReadRequest(evt);
+ }
+#endif // CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+ }
+ break;
+
+ case sl_bt_evt_connection_remote_used_features_id: {
+ // ChipLogProgress(DeviceLayer, "link layer features supported by the remote device");
+ }
+ break;
+
+ default:
+ ChipLogProgress(DeviceLayer, "evt_UNKNOWN id = %08" PRIx32, SL_BT_MSG_ID(evt->header));
+ break;
+ }
+
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+}
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
diff --git a/src/platform/silabs/SiWx917/BUILD.gn b/src/platform/silabs/SiWx917/BUILD.gn
new file mode 100644
index 0000000..b67c63c
--- /dev/null
+++ b/src/platform/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,125 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${chip_root}/src/platform/device.gni")
+
+import("${chip_root}/build/chip/buildconfig_header.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+
+silabs_platform_dir = "${chip_root}/src/platform/silabs"
+
+assert(chip_device_platform == "efr32")
+
+if (chip_enable_openthread) {
+ import("//build_overrides/openthread.gni")
+}
+
+if (chip_crypto == "platform") {
+ import("//build_overrides/mbedtls.gni")
+}
+
+static_library("EFR32") {
+ sources = [
+ "${silabs_platform_dir}/BLEManagerImpl.h",
+ "${silabs_platform_dir}/BlePlatformConfig.h",
+ "${silabs_platform_dir}/CHIPDevicePlatformConfig.h",
+ "${silabs_platform_dir}/CHIPDevicePlatformEvent.h",
+ "${silabs_platform_dir}/CHIPMem-Platform.cpp",
+ "${silabs_platform_dir}/CHIPPlatformConfig.h",
+ "${silabs_platform_dir}/ConfigurationManagerImpl.h",
+ "${silabs_platform_dir}/ConnectivityManagerImpl.h",
+ "${silabs_platform_dir}/DiagnosticDataProviderImpl.cpp",
+ "${silabs_platform_dir}/DiagnosticDataProviderImpl.h",
+ "${silabs_platform_dir}/InetPlatformConfig.h",
+ "${silabs_platform_dir}/KeyValueStoreManagerImpl.h",
+ "${silabs_platform_dir}/Logging.cpp",
+ "${silabs_platform_dir}/PlatformManagerImpl.h",
+ "${silabs_platform_dir}/SilabsConfig.cpp",
+ "${silabs_platform_dir}/SilabsConfig.h",
+ "${silabs_platform_dir}/SystemPlatformConfig.h",
+ "../../FreeRTOS/SystemTimeSupport.cpp",
+ "../../SingletonConfigurationManager.cpp",
+ "BLEManagerImpl.cpp",
+ "ConfigurationManagerImpl.cpp",
+ "KeyValueStoreManagerImpl.cpp",
+ "PlatformManagerImpl.cpp",
+ ]
+
+ if (chip_enable_ota_requestor) {
+ sources += [
+ "OTAImageProcessorImpl.cpp",
+ "OTAImageProcessorImpl.h",
+ ]
+ }
+
+ public_deps = [ "${chip_root}/src/platform:platform_base" ]
+
+ # Add platform crypto implementation
+ if (chip_crypto == "platform") {
+ sources += [
+ "CHIPCryptoPALPsaEfr32.cpp",
+ "Efr32OpaqueKeypair.h",
+ "Efr32PsaOpaqueKeypair.cpp",
+ "Efr32PsaOperationalKeystore.cpp",
+ "Efr32PsaOperationalKeystore.h",
+ ]
+
+ public_deps += [
+ "${chip_root}/src/crypto",
+ "${mbedtls_root}:mbedtls",
+ ]
+ }
+
+ # Add pigweed KVS
+ deps = [
+ "$dir_pw_kvs:crc16",
+ "$dir_pw_log",
+ ]
+ public_deps += [
+ "$dir_pw_checksum",
+ "$dir_pw_kvs",
+ ]
+ if (chip_enable_openthread) {
+ public_deps += [ "${chip_root}/third_party/openthread:openthread" ]
+
+ deps += [ "${chip_root}/third_party/openthread:openthread_cli" ]
+
+ sources += [
+ "${silabs_platform_dir}/ThreadStackManagerImpl.h",
+ "../../OpenThread/OpenThreadUtils.cpp",
+ "ConnectivityManagerImpl.cpp",
+ "ThreadStackManagerImpl.cpp",
+ ]
+
+ if (chip_mdns == "platform") {
+ sources += [ "../../OpenThread/DnssdImpl.cpp" ]
+ deps += [ "${chip_root}/src/lib/dnssd:platform_header" ]
+ }
+
+ public_configs = [
+ "${chip_root}/src/lib/address_resolve:default_address_resolve_config",
+ ]
+ }
+
+ if (chip_enable_wifi) {
+ sources += [
+ "${silabs_platform_dir}/ConnectivityManagerImpl_WIFI.cpp",
+ "${silabs_platform_dir}/NetworkCommissioningWiFiDriver.cpp",
+ "${silabs_platform_dir}/NetworkCommissioningWiFiDriver.h",
+ ]
+ }
+}
diff --git a/src/platform/silabs/SiWx917/CHIPCryptoPALPsaEfr32.cpp b/src/platform/silabs/SiWx917/CHIPCryptoPALPsaEfr32.cpp
new file mode 100644
index 0000000..13af1ae
--- /dev/null
+++ b/src/platform/silabs/SiWx917/CHIPCryptoPALPsaEfr32.cpp
@@ -0,0 +1,1879 @@
+/*
+ *
+ * Copyright (c) 2020-2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * PSA Crypto API based implementation of CHIP crypto primitives
+ * with Silicon Labs SDK modifications
+ */
+
+#include <crypto/CHIPCryptoPAL.h>
+
+#include <type_traits>
+
+// Include version header to get configuration information
+#include <mbedtls/version.h>
+
+#if !defined(MBEDTLS_PSA_CRYPTO_C)
+#error "This implementation needs PSA Crypto"
+#endif
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+#error "This implementation requires that PSA Crypto keys can be used for CSR generation"
+#endif
+
+#include "psa/crypto.h"
+
+// Go straight for the driver wrappers for speed on plaintext keys
+extern "C" {
+#include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers.h"
+}
+
+// Includes needed for SPAKE2+ ECP operations
+#include <mbedtls/bignum.h>
+#include <mbedtls/ecp.h>
+
+// Includes needed for certificate parsing
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#include <mbedtls/x509_crt.h>
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+#include <mbedtls/md.h>
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_csr.h>
+
+#if defined(MBEDTLS_ERROR_C)
+#include <mbedtls/error.h>
+#endif // defined(MBEDTLS_ERROR_C)
+
+#include <lib/core/CHIPSafeCasts.h>
+#include <lib/support/BufferWriter.h>
+#include <lib/support/BytesToHex.h>
+#include <lib/support/CHIPArgParser.hpp>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/SafeInt.h>
+#include <lib/support/SafePointerCast.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+#include <string.h>
+
+namespace chip {
+namespace Crypto {
+
+using chip::Platform::MemoryCalloc;
+using chip::Platform::MemoryFree;
+
+#define MAX_ERROR_STR_LEN 128
+#define NUM_BYTES_IN_SHA256_HASH 32
+
+// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro.
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x)
+#else
+#define CHIP_CRYPTO_PAL_PRIVATE(x) x
+#endif
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000)
+#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x)
+#else
+#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x
+#endif
+
+static void _log_mbedTLS_error(int error_code)
+{
+ if (error_code != 0)
+ {
+#if defined(MBEDTLS_ERROR_C)
+ char error_str[MAX_ERROR_STR_LEN];
+ mbedtls_strerror(error_code, error_str, sizeof(error_str));
+ ChipLogError(Crypto, "mbedTLS error: %s", error_str);
+#else
+ // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise
+ ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast<uint16_t>(error_code));
+#endif
+ }
+}
+
+static void _log_PSA_error(psa_status_t status)
+{
+ if (status != 0)
+ {
+ // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise
+ ChipLogError(Crypto, "PSA error: %ld", status);
+ }
+}
+
+static bool _isValidTagLength(size_t tag_length)
+{
+ if (tag_length == 8 || tag_length == 12 || tag_length == 16)
+ {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * @brief Compare two times
+ *
+ * @param t1 First time to compare
+ * @param t2 Second time to compare
+ * @return int 0 If both times are idential to the second, -1 if t1 < t2, 1 if t1 > t2.
+ */
+static int timeCompare(mbedtls_x509_time * t1, mbedtls_x509_time * t2)
+{
+ VerifyOrReturnValue(t1->year >= t2->year, -1);
+ VerifyOrReturnValue(t1->year <= t2->year, 1);
+ // Same year
+ VerifyOrReturnValue(t1->mon >= t2->mon, -1);
+ VerifyOrReturnValue(t1->mon <= t2->mon, 1);
+ // Same month
+ VerifyOrReturnValue(t1->day >= t2->day, -1);
+ VerifyOrReturnValue(t1->day <= t2->day, 1);
+ // Same day
+ VerifyOrReturnValue(t1->hour >= t2->hour, -1);
+ VerifyOrReturnValue(t1->hour <= t2->hour, 1);
+ // Same hour
+ VerifyOrReturnValue(t1->min >= t2->min, -1);
+ VerifyOrReturnValue(t1->min <= t2->min, 1);
+ // Same minute
+ VerifyOrReturnValue(t1->sec >= t2->sec, -1);
+ VerifyOrReturnValue(t1->sec <= t2->sec, 1);
+ // Same second
+ return 0;
+}
+
+CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
+ const uint8_t * key, size_t key_length, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
+ uint8_t * tag, size_t tag_length)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t output_length = 0;
+ uint8_t * buffer = nullptr;
+ bool allocated_buffer = false;
+
+ VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(key_length == kAES_CCM128_Key_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(key_length == kAES_CCM128_Key_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ // If the ciphertext and tag outputs aren't a contiguous buffer, the PSA API requires buffer copying
+ if (Uint8::to_uchar(ciphertext) + plaintext_length != Uint8::to_uchar(tag))
+ {
+ buffer = (uint8_t *) MemoryCalloc(1, plaintext_length + tag_length);
+ allocated_buffer = true;
+ VerifyOrExit(buffer != nullptr, error = CHIP_ERROR_NO_MEMORY);
+ }
+
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
+ psa_set_key_bits(&attr, key_length * 8);
+ psa_set_key_algorithm(&attr, PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8));
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT);
+
+ status = psa_driver_wrapper_aead_encrypt(
+ &attr, Uint8::to_const_uchar(key), key_length, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length),
+ Uint8::to_const_uchar(nonce), nonce_length, Uint8::to_const_uchar(aad), aad_length, Uint8::to_const_uchar(plaintext),
+ plaintext_length, allocated_buffer ? buffer : ciphertext, plaintext_length + tag_length, &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == plaintext_length + tag_length, error = CHIP_ERROR_INTERNAL);
+
+ if (allocated_buffer)
+ {
+ memcpy(Uint8::to_uchar(ciphertext), buffer, plaintext_length);
+ memcpy(Uint8::to_uchar(tag), buffer + plaintext_length, tag_length);
+ memset(buffer, 0, plaintext_length + tag_length);
+ }
+
+exit:
+ if (allocated_buffer)
+ {
+ MemoryFree(buffer);
+ }
+ psa_reset_key_attributes(&attr);
+ return error;
+}
+
+CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len,
+ const uint8_t * tag, size_t tag_length, const uint8_t * key, size_t key_length, const uint8_t * nonce,
+ size_t nonce_length, uint8_t * plaintext)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t output_length = 0;
+ uint8_t * buffer = nullptr;
+ bool allocated_buffer = false;
+
+ VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(key_length == kAES_CCM128_Key_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ // If the ciphertext and tag outputs aren't a contiguous buffer, the PSA API requires buffer copying
+ if (Uint8::to_const_uchar(ciphertext) + ciphertext_len != Uint8::to_const_uchar(tag))
+ {
+ buffer = (uint8_t *) MemoryCalloc(1, ciphertext_len + tag_length);
+ allocated_buffer = true;
+ VerifyOrExit(buffer != nullptr, error = CHIP_ERROR_NO_MEMORY);
+ }
+
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
+ psa_set_key_bits(&attr, key_length * 8);
+ psa_set_key_algorithm(&attr, PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8));
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DECRYPT);
+
+ if (allocated_buffer)
+ {
+ memcpy(buffer, ciphertext, ciphertext_len);
+ memcpy(buffer + ciphertext_len, tag, tag_length);
+ }
+
+ status = psa_driver_wrapper_aead_decrypt(
+ &attr, Uint8::to_const_uchar(key), key_length, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length),
+ Uint8::to_const_uchar(nonce), nonce_length, Uint8::to_const_uchar(aad), aad_len, allocated_buffer ? buffer : ciphertext,
+ ciphertext_len + tag_length, plaintext, ciphertext_len, &output_length);
+
+ if (allocated_buffer)
+ {
+ memset(buffer, 0, ciphertext_len + tag_length);
+ }
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == ciphertext_len, error = CHIP_ERROR_INTERNAL);
+exit:
+ if (allocated_buffer)
+ {
+ MemoryFree(buffer);
+ }
+
+ psa_reset_key_attributes(&attr);
+ return error;
+}
+
+CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
+{
+ size_t output_length = 0;
+
+ psa_crypto_init();
+
+ const psa_status_t result =
+ psa_hash_compute(PSA_ALG_SHA_256, data, data_length, out_buffer, PSA_HASH_LENGTH(PSA_ALG_SHA_256), &output_length);
+
+ VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
+{
+ size_t output_length = 0;
+
+ psa_crypto_init();
+
+ const psa_status_t result =
+ psa_hash_compute(PSA_ALG_SHA_1, data, data_length, out_buffer, PSA_HASH_LENGTH(PSA_ALG_SHA_1), &output_length);
+
+ VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_1), CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(psa_hash_operation_t),
+ "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying psa_hash_operation_t");
+
+static inline psa_hash_operation_t * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context)
+{
+ return SafePointerCast<psa_hash_operation_t *>(context);
+}
+
+Hash_SHA256_stream::Hash_SHA256_stream(void)
+{
+ psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+ const psa_hash_operation_t initial_context = PSA_HASH_OPERATION_INIT;
+ memcpy(context, &initial_context, sizeof(psa_hash_operation_t));
+}
+
+Hash_SHA256_stream::~Hash_SHA256_stream(void)
+{
+ psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+ psa_hash_abort(context);
+ Clear();
+}
+
+CHIP_ERROR Hash_SHA256_stream::Begin(void)
+{
+ psa_crypto_init();
+
+ psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+ *context = PSA_HASH_OPERATION_INIT;
+ const psa_status_t result = psa_hash_setup(context, PSA_ALG_SHA_256);
+
+ VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data)
+{
+ psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+ const psa_status_t result = psa_hash_update(context, Uint8::to_const_uchar(data.data()), data.size());
+
+ VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer)
+{
+ CHIP_ERROR result = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ size_t output_length = 0;
+ psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+
+ VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ // Clone the context first since calculating the digest finishes the operation
+ psa_hash_operation_t digest_context = PSA_HASH_OPERATION_INIT;
+ status = psa_hash_clone(context, &digest_context);
+
+ VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+ // Calculate digest on the cloned context
+ status = psa_hash_finish(&digest_context, Uint8::to_uchar(out_buffer.data()), out_buffer.size(), &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, result = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), result = CHIP_ERROR_INTERNAL);
+exit:
+ psa_hash_abort(&digest_context);
+ return result;
+}
+
+CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer)
+{
+ psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+ size_t output_length = 0;
+
+ VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+ const psa_status_t status = psa_hash_finish(context, Uint8::to_uchar(out_buffer.data()), out_buffer.size(), &output_length);
+
+ VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+void Hash_SHA256_stream::Clear(void)
+{
+ psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+ psa_hash_abort(context);
+}
+
+CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length,
+ const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length)
+{
+ VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(secret_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+ // Salt is optional
+ if (salt_length > 0)
+ {
+ VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ }
+
+ VerifyOrReturnError(info_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(info != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+
+ psa_crypto_init();
+
+ status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+ if (salt_length > 0)
+ {
+ status =
+ psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, Uint8::to_const_uchar(salt), salt_length);
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ }
+
+ status =
+ psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, Uint8::to_const_uchar(secret), secret_length);
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+ status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO, Uint8::to_const_uchar(info), info_length);
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+ status = psa_key_derivation_output_bytes(&operation, out_buffer, out_length);
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+exit:
+ psa_key_derivation_abort(&operation);
+
+ return error;
+}
+
+CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
+ uint8_t * out_buffer, size_t out_length)
+{
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+ size_t output_length = 0;
+
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
+ psa_set_key_bits(&attr, key_length * 8);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
+
+ status = psa_driver_wrapper_mac_compute(&attr, Uint8::to_const_uchar(key), key_length, PSA_ALG_HMAC(PSA_ALG_SHA_256),
+ Uint8::to_const_uchar(message), message_length, out_buffer, out_length, &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL);
+exit:
+ psa_mac_abort(&operation);
+ psa_reset_key_attributes(&attr);
+ return error;
+}
+
+CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
+ unsigned int iteration_count, uint32_t key_length, uint8_t * output)
+{
+ // TODO: replace inlined algorithm with usage of the PSA key derivation API once implemented
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t output_length = 0;
+
+ // Align these buffers on the native data size to speed up the XOR
+ static const size_t hash_size_in_native =
+ ((PSA_HASH_LENGTH(PSA_ALG_SHA_256) + sizeof(unsigned int) - 1) / sizeof(unsigned int));
+ static_assert(hash_size_in_native * sizeof(unsigned int) >= PSA_HASH_LENGTH(PSA_ALG_SHA_256));
+
+ unsigned int md1_buffer[hash_size_in_native];
+ unsigned int work_buffer[hash_size_in_native];
+ uint8_t * md1 = (uint8_t *) md1_buffer;
+ uint8_t * work = (uint8_t *) work_buffer;
+
+ size_t use_len;
+ unsigned char * out_p = output;
+ uint8_t * U1 = (uint8_t *) MemoryCalloc(1, slen + 4);
+
+ VerifyOrExit(U1 != nullptr, error = CHIP_ERROR_NO_MEMORY);
+ VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
+ psa_set_key_bits(&attr, plen * 8);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
+ psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
+
+ // Start with initializing the salt + counter
+ memcpy(U1, salt, slen);
+ U1[slen] = 0;
+ U1[slen + 1] = 0;
+ U1[slen + 2] = 0;
+ U1[slen + 3] = 1;
+
+ // Loop until we have generated the requested key length
+ while (key_length)
+ {
+ // U1 ends up in work
+ status = psa_driver_wrapper_mac_compute(&attr, password, plen, PSA_ALG_HMAC(PSA_ALG_SHA_256), U1, slen + 4, work,
+ PSA_HASH_LENGTH(PSA_ALG_SHA_256), &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL);
+
+ memcpy(md1, work, PSA_HASH_LENGTH(PSA_ALG_SHA_256));
+
+ for (size_t i = 1; i < iteration_count; i++)
+ {
+ // U2 ends up in md1
+ //
+
+ status = psa_driver_wrapper_mac_compute(&attr, password, plen, PSA_ALG_HMAC(PSA_ALG_SHA_256), md1, sizeof(md1_buffer),
+ md1, sizeof(md1_buffer), &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL);
+
+ // U1 xor U2
+ //
+ for (size_t j = 0; j < hash_size_in_native; j++)
+ {
+ work_buffer[j] ^= md1_buffer[j];
+ }
+ }
+
+ use_len = (key_length < PSA_HASH_LENGTH(PSA_ALG_SHA_256)) ? key_length : PSA_HASH_LENGTH(PSA_ALG_SHA_256);
+ memcpy(out_p, work, use_len);
+
+ key_length -= (uint32_t) use_len;
+ out_p += use_len;
+
+ for (size_t i = 4; i > 0; i--)
+ {
+ if (++U1[slen + i - 1] != 0)
+ {
+ break;
+ }
+ }
+ }
+
+exit:
+ MemoryFree(U1);
+ psa_reset_key_attributes(&attr);
+ return error;
+}
+
+CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold)
+{
+ // PSA Crypto has its own entropy and doesn't support an override mechanism
+ (void) fn_source;
+ (void) p_source;
+ (void) threshold;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
+{
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+ psa_crypto_init();
+ const psa_status_t result = psa_generate_random(Uint8::to_uchar(out_buffer), out_length);
+ VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+// CryptoRNG's definition is needed to use the mbedTLS-backed SPAKE2+ and certificate operations
+static int CryptoRNG(void * ctxt, uint8_t * out_buffer, size_t out_length)
+{
+ return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1;
+}
+
+// Mapping function is used as part of the certificate operations
+mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType)
+{
+ switch (keyType)
+ {
+ case SupportedECPKeyTypes::ECP256R1:
+ return MBEDTLS_ECP_DP_SECP256R1;
+ default:
+ return MBEDTLS_ECP_DP_NONE;
+ }
+}
+
+/*******************************************************************************
+ *
+ * WARNING: The default (base) implementation of P256Keypair is UNSAFE!
+ *
+ * Because of the way CHIPCryptoPAL has evolved, it is dictating how a base
+ * P256Keypair should behave. This includes:
+ * * Allowing using a P256 key for both ECDSA and ECDH operations
+ * * Needing to support copying a key through Serialize()/Deserialize()
+ * operations. This can't easily be done opaquely on an opaque backend
+ * without convoluted forms of reference tracking.
+ * * Not including a way to figure out whether the created key is supposed
+ * to be ephemeral or long-lived.
+ * * Needing to support ingestion of specific-format keys through
+ * Deserialize() (to support e.g. the example DAC provider).
+ *
+ * These conditions have lead to the base implementation of this class in this
+ * crypto backend being backed by a plaintext key buffer instead of opaque key
+ * references. Usage of the base class is strongly discouraged, and is only
+ * implemented to support the in-tree examples which instantiate keys of this
+ * base class.
+ *
+ ******************************************************************************/
+
+typedef struct
+{
+ uint8_t privkey[32];
+ size_t bitlen;
+} psa_plaintext_ecp_keypair;
+
+static inline psa_plaintext_ecp_keypair * to_keypair(P256KeypairContext * context)
+{
+ return SafePointerCast<psa_plaintext_ecp_keypair *>(context);
+}
+
+static inline const psa_plaintext_ecp_keypair * to_const_keypair(const P256KeypairContext * context)
+{
+ return SafePointerCast<const psa_plaintext_ecp_keypair *>(context);
+}
+
+CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t output_length = 0;
+ const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair);
+
+ VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attr, keypair->bitlen);
+ psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE);
+
+ // use imported key to sign a message
+ status =
+ psa_driver_wrapper_sign_message(&attr, keypair->privkey, PSA_BITS_TO_BYTES(keypair->bitlen), PSA_ALG_ECDSA(PSA_ALG_SHA_256),
+ msg, msg_length, out_signature.Bytes(), out_signature.Capacity(), &output_length);
+
+ VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(output_length == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(out_signature.SetLength(output_length) == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_PSA_error(status);
+ psa_reset_key_attributes(&attr);
+
+ return error;
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length,
+ const P256ECDSASignature & signature) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+
+ VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attr, 256);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
+ psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+
+ // use imported key to verify a message
+ status = psa_driver_wrapper_verify_message(&attr, Uint8::to_const_uchar(*this), Length(), PSA_ALG_ECDSA(PSA_ALG_SHA_256), msg,
+ msg_length, signature.ConstBytes(), signature.Length());
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE);
+exit:
+ _log_PSA_error(status);
+ psa_reset_key_attributes(&attr);
+
+ return error;
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
+ const P256ECDSASignature & signature) const
+{
+ VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(hash_length == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(signature.Length() == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INVALID_ARGUMENT);
+
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+
+ // Step 1: import public key as volatile
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attr, 256);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_HASH);
+ psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+
+ // use imported key to verify a hash
+ status = psa_driver_wrapper_verify_hash(&attr, Uint8::to_const_uchar(*this), Length(), PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash,
+ hash_length, signature.ConstBytes(), signature.Length());
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE);
+exit:
+ _log_PSA_error(status);
+ psa_reset_key_attributes(&attr);
+ return error;
+}
+
+CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
+{
+ // Todo: replace with driver call once key derivation through the driver wrapper has been figured out
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ mbedtls_svc_key_id_t key_id = 0;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t output_length = 0;
+ const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair);
+
+ VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED);
+
+ // Step 1: import plaintext key as volatile for ECDH
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attr, keypair->bitlen);
+ psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
+
+ status = psa_import_key(&attr, keypair->privkey, PSA_BITS_TO_BYTES(keypair->bitlen), &key_id);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+ // Step 2: do key derivation
+ status = psa_raw_key_agreement(PSA_ALG_ECDH, key_id, Uint8::to_const_uchar(remote_public_key), remote_public_key.Length(),
+ Uint8::to_uchar(out_secret),
+ (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(), &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ SuccessOrExit(out_secret.SetLength(output_length));
+
+exit:
+ _log_PSA_error(status);
+ // Step 3: destroy imported key
+ psa_reset_key_attributes(&attr);
+ if (key_id != 0)
+ {
+ psa_destroy_key(key_id);
+ }
+ return error;
+}
+
+void ClearSecretData(uint8_t * buf, size_t len)
+{
+ mbedtls_platform_zeroize(buf, len);
+}
+
+// THE BELOW IS FROM `third_party/openthread/repo/third_party/mbedtls/repo/library/constant_time.c` since
+// mbedtls_ct_memcmp is not available on Linux somehow :(
+int mbedtls_ct_memcmp_copy(const void * a, const void * b, size_t n)
+{
+ size_t i;
+ volatile const unsigned char * A = (volatile const unsigned char *) a;
+ volatile const unsigned char * B = (volatile const unsigned char *) b;
+ volatile unsigned char diff = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ /* Read volatile data in order before computing diff.
+ * This avoids IAR compiler warning:
+ * 'the order of volatile accesses is undefined ..' */
+ unsigned char x = A[i], y = B[i];
+ diff |= x ^ y;
+ }
+
+ return ((int) diff);
+}
+
+bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n)
+{
+ return mbedtls_ct_memcmp_copy(a, b, n) == 0;
+}
+
+CHIP_ERROR P256Keypair::Initialize()
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_plaintext_ecp_keypair * keypair = to_keypair(&mKeypair);
+ size_t output_length;
+
+ if (mInitialized)
+ {
+ return CHIP_ERROR_INCORRECT_STATE;
+ }
+
+ // Step 1: Generate a volatile new key
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ psa_crypto_init();
+
+ psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attr, 256);
+ psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
+
+ status = psa_driver_wrapper_generate_key(&attr, keypair->privkey, sizeof(keypair->privkey), &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == kP256_PrivateKey_Length, error = CHIP_ERROR_INTERNAL);
+
+ keypair->bitlen = 256;
+
+ // Step 2: Export the public key into the pubkey member
+ status = psa_driver_wrapper_export_public_key(&attr, keypair->privkey, sizeof(keypair->privkey), Uint8::to_uchar(mPublicKey),
+ mPublicKey.Length(), &output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(output_length == kP256_PublicKey_Length, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_PSA_error(status);
+ if (error == CHIP_NO_ERROR)
+ {
+ mInitialized = true;
+ }
+ psa_reset_key_attributes(&attr);
+
+ return error;
+}
+
+CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair);
+ size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
+ Encoding::BufferWriter bbuf(output, len);
+
+ VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED);
+
+ bbuf.Put(mPublicKey, mPublicKey.Length());
+
+ VerifyOrExit(bbuf.Available() == sizeof(keypair->privkey), error = CHIP_ERROR_INTERNAL);
+
+ bbuf.Put(keypair->privkey, PSA_BITS_TO_BYTES(keypair->bitlen));
+ VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ output.SetLength(bbuf.Needed());
+
+exit:
+ return error;
+}
+
+CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_plaintext_ecp_keypair * keypair = to_keypair(&mKeypair);
+ Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
+
+ VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ Clear();
+
+ memcpy(keypair->privkey, Uint8::to_uchar(input) + mPublicKey.Length(), kP256_PrivateKey_Length);
+ keypair->bitlen = 256;
+
+ bbuf.Put((const uint8_t *) input, mPublicKey.Length());
+ VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
+
+ mInitialized = true;
+
+exit:
+ return error;
+}
+
+void P256Keypair::Clear()
+{
+ if (mInitialized)
+ {
+ psa_plaintext_ecp_keypair * keypair = to_keypair(&mKeypair);
+ memset(keypair, 0, sizeof(psa_plaintext_ecp_keypair));
+ mInitialized = false;
+ }
+}
+
+P256Keypair::~P256Keypair()
+{
+ Clear();
+}
+
+CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
+{
+ MutableByteSpan csr(out_csr, csr_length);
+ CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr);
+ csr_length = (CHIP_NO_ERROR == err) ? csr.size() : 0;
+ return err;
+}
+
+CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_length, P256PublicKey & pubkey)
+{
+#if defined(MBEDTLS_X509_CSR_PARSE_C)
+ ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr_buf, csr_length));
+
+ // TODO: For some embedded targets, mbedTLS library doesn't have mbedtls_x509_csr_parse_der, and mbedtls_x509_csr_parse_free.
+ // Taking a step back, embedded targets likely will not process CSR requests. Adding this action item to reevaluate
+ // this if there's a need for this processing for embedded targets.
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ size_t pubkey_size = 0;
+
+ mbedtls_ecp_keypair * keypair = nullptr;
+
+ P256ECDSASignature signature;
+ MutableByteSpan out_raw_sig_span(signature.Bytes(), signature.Capacity());
+
+ mbedtls_x509_csr csr;
+ mbedtls_x509_csr_init(&csr);
+
+ int result = mbedtls_x509_csr_parse_der(&csr, csr_buf, csr_length);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // Verify the signature algorithm and public key type
+ VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_md) == MBEDTLS_MD_SHA256, error = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
+ VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_pk) == MBEDTLS_PK_ECDSA, error = CHIP_ERROR_WRONG_KEY_TYPE);
+
+ keypair = mbedtls_pk_ec(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(pk));
+
+ // Copy the public key from the CSR
+ result = mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q),
+ MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey), pubkey.Length());
+
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL);
+
+ // Convert DER signature to raw signature
+ error = EcdsaAsn1SignatureToRaw(kP256_FE_Length,
+ ByteSpan{ csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(p),
+ csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(len) },
+ out_raw_sig_span);
+
+ VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(out_raw_sig_span.size() == (kP256_FE_Length * 2), error = CHIP_ERROR_INTERNAL);
+ signature.SetLength(out_raw_sig_span.size());
+
+ // Verify the signature using the public key
+ error = pubkey.ECDSA_validate_msg_signature(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(p),
+ csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(len), signature);
+
+ SuccessOrExit(error);
+
+exit:
+ mbedtls_x509_csr_free(&csr);
+ _log_mbedTLS_error(result);
+ return error;
+#else
+ ChipLogError(Crypto, "MBEDTLS_X509_CSR_PARSE_C is not enabled. CSR cannot be parsed");
+ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+#endif
+}
+
+typedef struct Spake2p_Context
+{
+ mbedtls_ecp_group curve;
+ mbedtls_ecp_point M;
+ mbedtls_ecp_point N;
+ mbedtls_ecp_point X;
+ mbedtls_ecp_point Y;
+ mbedtls_ecp_point L;
+ mbedtls_ecp_point Z;
+ mbedtls_ecp_point V;
+
+ mbedtls_mpi w0;
+ mbedtls_mpi w1;
+ mbedtls_mpi xy;
+ mbedtls_mpi tempbn;
+} Spake2p_Context;
+
+static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context)
+{
+ return SafePointerCast<Spake2p_Context *>(context);
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal(void)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ memset(context, 0, sizeof(Spake2p_Context));
+
+ mbedtls_ecp_group_init(&context->curve);
+ result = mbedtls_ecp_group_load(&context->curve, MBEDTLS_ECP_DP_SECP256R1);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) != nullptr, error = CHIP_ERROR_INTERNAL);
+
+ mbedtls_ecp_point_init(&context->M);
+ mbedtls_ecp_point_init(&context->N);
+ mbedtls_ecp_point_init(&context->X);
+ mbedtls_ecp_point_init(&context->Y);
+ mbedtls_ecp_point_init(&context->L);
+ mbedtls_ecp_point_init(&context->V);
+ mbedtls_ecp_point_init(&context->Z);
+ M = &context->M;
+ N = &context->N;
+ X = &context->X;
+ Y = &context->Y;
+ L = &context->L;
+ V = &context->V;
+ Z = &context->Z;
+
+ mbedtls_mpi_init(&context->w0);
+ mbedtls_mpi_init(&context->w1);
+ mbedtls_mpi_init(&context->xy);
+ mbedtls_mpi_init(&context->tempbn);
+ w0 = &context->w0;
+ w1 = &context->w1;
+ xy = &context->xy;
+ tempbn = &context->tempbn;
+
+ G = &context->curve.G;
+ order = &context->curve.N;
+
+ return error;
+
+exit:
+ _log_mbedTLS_error(result);
+ Clear();
+ return error;
+}
+
+void Spake2p_P256_SHA256_HKDF_HMAC::Clear()
+{
+ VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT);
+
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ mbedtls_ecp_point_free(&context->M);
+ mbedtls_ecp_point_free(&context->N);
+ mbedtls_ecp_point_free(&context->X);
+ mbedtls_ecp_point_free(&context->Y);
+ mbedtls_ecp_point_free(&context->L);
+ mbedtls_ecp_point_free(&context->Z);
+ mbedtls_ecp_point_free(&context->V);
+
+ mbedtls_mpi_free(&context->w0);
+ mbedtls_mpi_free(&context->w1);
+ mbedtls_mpi_free(&context->xy);
+ mbedtls_mpi_free(&context->tempbn);
+
+ mbedtls_ecp_group_free(&context->curve);
+
+ state = CHIP_SPAKE2P_STATE::PREINIT;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len,
+ MutableByteSpan & out_span)
+{
+ HMAC_sha hmac;
+ VerifyOrReturnError(out_span.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+ ReturnErrorOnFailure(hmac.HMAC_SHA256(key, key_len, in, in_len, out_span.data(), kSHA256_Hash_Length));
+ out_span = out_span.SubSpan(0, kSHA256_Hash_Length);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len,
+ const uint8_t * in, size_t in_len)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ uint8_t computed_mac[kSHA256_Hash_Length];
+ MutableByteSpan computed_mac_span{ computed_mac };
+ VerifyOrExit(mac_len == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ SuccessOrExit(error = Mac(key, key_len, in, in_len, computed_mac_span));
+ VerifyOrExit(computed_mac_span.size() == mac_len, error = CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(IsBufferContentEqualConstantTime(mac, computed_mac, kSHA256_Hash_Length), error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+ return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_len, void * fe)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ result = mbedtls_mpi_read_binary((mbedtls_mpi *) fe, Uint8::to_const_uchar(in), in_len);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fe, (mbedtls_mpi *) fe, (const mbedtls_mpi *) order);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+ return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len)
+{
+ if (mbedtls_mpi_write_binary((const mbedtls_mpi *) fe, Uint8::to_uchar(out), out_len) != 0)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ result = mbedtls_ecp_gen_privkey(&context->curve, (mbedtls_mpi *) fe, CryptoRNG, nullptr);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+ return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, const void * fe2)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ result = mbedtls_mpi_mul_mpi((mbedtls_mpi *) fer, (const mbedtls_mpi *) fe1, (const mbedtls_mpi *) fe2);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fer, (mbedtls_mpi *) fer, (const mbedtls_mpi *) order);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+ return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R)
+{
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ if (mbedtls_ecp_point_read_binary(&context->curve, (mbedtls_ecp_point *) R, Uint8::to_const_uchar(in), in_len) != 0)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * out, size_t out_len)
+{
+ memset(out, 0, out_len);
+
+ size_t mbedtls_out_len = out_len;
+
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ if (mbedtls_ecp_point_write_binary(&context->curve, (const mbedtls_ecp_point *) R, MBEDTLS_ECP_PF_UNCOMPRESSED,
+ &mbedtls_out_len, Uint8::to_uchar(out), out_len) != 0)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1)
+{
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ if (mbedtls_ecp_mul(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1,
+ CryptoRNG, nullptr) != 0)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2,
+ const void * fe2)
+{
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ if (mbedtls_ecp_muladd(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1,
+ (const mbedtls_mpi *) fe2, (const mbedtls_ecp_point *) P2) != 0)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R)
+{
+ mbedtls_ecp_point * Rp = (mbedtls_ecp_point *) R;
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ if (mbedtls_mpi_sub_mpi(&Rp->CHIP_CRYPTO_PAL_PRIVATE(Y), &context->curve.P, &Rp->CHIP_CRYPTO_PAL_PRIVATE(Y)) != 0)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointCofactorMul(void * R)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ mbedtls_ecp_group curve;
+ mbedtls_mpi w1_bn;
+ mbedtls_ecp_point Ltemp;
+
+ mbedtls_ecp_group_init(&curve);
+ mbedtls_mpi_init(&w1_bn);
+ mbedtls_ecp_point_init(&Ltemp);
+
+ result = mbedtls_ecp_group_load(&curve, MBEDTLS_ECP_DP_SECP256R1);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ result = mbedtls_mpi_read_binary(&w1_bn, Uint8::to_const_uchar(w1in), w1in_len);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ result = mbedtls_mpi_mod_mpi(&w1_bn, &w1_bn, &curve.N);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ result = mbedtls_ecp_mul(&curve, &Ltemp, &w1_bn, &curve.G, CryptoRNG, nullptr);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ memset(Lout, 0, *L_len);
+
+ result = mbedtls_ecp_point_write_binary(&curve, &Ltemp, MBEDTLS_ECP_PF_UNCOMPRESSED, L_len, Uint8::to_uchar(Lout), *L_len);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+ mbedtls_ecp_point_free(&Ltemp);
+ mbedtls_mpi_free(&w1_bn);
+ mbedtls_ecp_group_free(&curve);
+
+ return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R)
+{
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+ if (mbedtls_ecp_check_pubkey(&context->curve, (mbedtls_ecp_point *) R) != 0)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+constexpr uint8_t sOID_AttributeType_CommonName[] = { 0x55, 0x04, 0x03 };
+constexpr uint8_t sOID_AttributeType_MatterVendorId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x01 };
+constexpr uint8_t sOID_AttributeType_MatterProductId[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x02 };
+constexpr uint8_t sOID_SigAlgo_ECDSAWithSHA256[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 };
+constexpr uint8_t sOID_Extension_BasicConstraints[] = { 0x55, 0x1D, 0x13 };
+constexpr uint8_t sOID_Extension_KeyUsage[] = { 0x55, 0x1D, 0x0F };
+constexpr uint8_t sOID_Extension_SubjectKeyIdentifier[] = { 0x55, 0x1D, 0x0E };
+constexpr uint8_t sOID_Extension_AuthorityKeyIdentifier[] = { 0x55, 0x1D, 0x23 };
+
+/**
+ * Compares an mbedtls_asn1_buf structure (oidBuf) to a reference OID represented as uint8_t array (oid).
+ */
+#define OID_CMP(oid, oidBuf) \
+ ((MBEDTLS_ASN1_OID == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(tag)) && \
+ (sizeof(oid) == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) && \
+ (memcmp((oid), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(p), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) == 0))
+
+CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+ mbedtls_x509_crt mbed_cert;
+ unsigned char * p = nullptr;
+ const unsigned char * end = nullptr;
+ size_t len = 0;
+ bool extBasicPresent = false;
+ bool extKeyUsagePresent = false;
+
+ VerifyOrReturnError(!cert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
+
+ mbedtls_x509_crt_init(&mbed_cert);
+
+ result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(cert.data()), cert.size());
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // "version" value is 1 higher than the actual encoded value.
+ VerifyOrExit(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(version) - 1 == 2, error = CHIP_ERROR_INTERNAL);
+
+ // Verify signature algorithms is ECDSA with SHA256.
+ VerifyOrExit(OID_CMP(sOID_SigAlgo_ECDSAWithSHA256, mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(sig_oid)),
+ error = CHIP_ERROR_INTERNAL);
+
+ // Verify public key presence and format.
+ {
+ Crypto::P256PublicKey pubkey;
+ SuccessOrExit(error = ExtractPubkeyFromX509Cert(cert, pubkey));
+ }
+
+ p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
+ end = p + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ while (p < end)
+ {
+ mbedtls_x509_buf extOID = { 0, 0, nullptr };
+ int extCritical = 0;
+
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ /* Get extension ID */
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(tag) = MBEDTLS_ASN1_OID;
+ extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(len) = len;
+ extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(p) = p;
+ p += len;
+
+ /* Get optional critical */
+ result = mbedtls_asn1_get_bool(&p, end, &extCritical);
+ VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL);
+
+ /* Data should be octet string type */
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ if (OID_CMP(sOID_Extension_BasicConstraints, extOID))
+ {
+ int isCA = 0;
+ int pathLen = -1;
+ unsigned char * seqStart = p;
+
+ VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL);
+ extBasicPresent = true;
+
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+ if (len > 0)
+ {
+ result = mbedtls_asn1_get_bool(&p, end, &isCA);
+ VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL);
+
+ if (p != seqStart + len)
+ {
+ result = mbedtls_asn1_get_int(&p, end, &pathLen);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+ }
+ }
+
+ if (certType == AttestationCertType::kDAC)
+ {
+ VerifyOrExit(!isCA && pathLen == -1, error = CHIP_ERROR_INTERNAL);
+ }
+ else if (certType == AttestationCertType::kPAI)
+ {
+ VerifyOrExit(isCA && pathLen == 0, error = CHIP_ERROR_INTERNAL);
+ }
+ else
+ {
+ VerifyOrExit(isCA && (pathLen == -1 || pathLen == 0 || pathLen == 1), error = CHIP_ERROR_INTERNAL);
+ }
+ }
+ else if (OID_CMP(sOID_Extension_KeyUsage, extOID))
+ {
+ mbedtls_x509_bitstring bs = { 0, 0, nullptr };
+ unsigned int keyUsage = 0;
+
+ VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL);
+ extKeyUsagePresent = true;
+
+ result = mbedtls_asn1_get_bitstring(&p, p + len, &bs);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ for (size_t i = 0; i < bs.CHIP_CRYPTO_PAL_PRIVATE_X509(len) && i < sizeof(unsigned int); i++)
+ {
+ keyUsage |= static_cast<unsigned int>(bs.CHIP_CRYPTO_PAL_PRIVATE_X509(p)[i]) << (8 * i);
+ }
+
+ if (certType == AttestationCertType::kDAC)
+ {
+ // SHALL only have the digitalSignature bit set.
+ VerifyOrExit(keyUsage == MBEDTLS_X509_KU_DIGITAL_SIGNATURE, error = CHIP_ERROR_INTERNAL);
+ }
+ else
+ {
+ bool keyCertSignFlag = keyUsage & MBEDTLS_X509_KU_KEY_CERT_SIGN;
+ bool crlSignFlag = keyUsage & MBEDTLS_X509_KU_CRL_SIGN;
+ bool otherFlags =
+ keyUsage & ~(MBEDTLS_X509_KU_CRL_SIGN | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_DIGITAL_SIGNATURE);
+ VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, error = CHIP_ERROR_INTERNAL);
+ }
+ }
+ else
+ {
+ p += len;
+ }
+ }
+
+ // Verify basic and key usage extensions are present.
+ VerifyOrExit(extBasicPresent && extKeyUsagePresent, error = CHIP_ERROR_INTERNAL);
+
+ // Verify that SKID and AKID extensions are present.
+ {
+ uint8_t kidBuf[kSubjectKeyIdentifierLength];
+ MutableByteSpan kid(kidBuf);
+ SuccessOrExit(error = ExtractSKIDFromX509Cert(cert, kid));
+ if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI)
+ {
+ // Mandatory extension for DAC and PAI certs.
+ SuccessOrExit(error = ExtractAKIDFromX509Cert(cert, kid));
+ }
+ }
+
+exit:
+ _log_mbedTLS_error(result);
+ mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+ (void) cert;
+ (void) certType;
+ CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+ return error;
+}
+
+CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate,
+ size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen,
+ CertificateChainValidationResult & result)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ mbedtls_x509_crt certChain;
+ mbedtls_x509_crt rootCert;
+ mbedtls_x509_time leaf_valid_from;
+ mbedtls_x509_crt * cert = NULL;
+ int mbedResult;
+ uint32_t flags;
+ int compare_from = 0;
+ int compare_until = 0;
+
+ result = CertificateChainValidationResult::kInternalFrameworkError;
+
+ VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0,
+ (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
+ VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0,
+ (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
+
+ mbedtls_x509_crt_init(&certChain);
+ mbedtls_x509_crt_init(&rootCert);
+
+ /* Start of chain */
+ mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(leafCertificate), leafCertificateLen);
+ VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kLeafFormatInvalid, error = CHIP_ERROR_INTERNAL));
+ leaf_valid_from = certChain.valid_from;
+
+ /* Add the intermediate to the chain, if present */
+ if (caCertificate != nullptr && caCertificateLen > 0)
+ {
+ mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(caCertificate), caCertificateLen);
+ VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kICAFormatInvalid, error = CHIP_ERROR_INTERNAL));
+ }
+
+ /* Parse the root cert */
+ mbedResult = mbedtls_x509_crt_parse(&rootCert, Uint8::to_const_uchar(rootCertificate), rootCertificateLen);
+ VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kRootFormatInvalid, error = CHIP_ERROR_INTERNAL));
+
+ /* Validates that intermediate and root certificates are valid at the time of the leaf certificate's start time. */
+ compare_from = timeCompare(&leaf_valid_from, &rootCert.valid_from);
+ compare_until = timeCompare(&leaf_valid_from, &rootCert.valid_to);
+ VerifyOrExit((compare_from >= 0) && (compare_until <= 0),
+ (result = CertificateChainValidationResult::kChainInvalid, error = CHIP_ERROR_CERT_NOT_TRUSTED));
+ cert = certChain.next;
+ while (cert)
+ {
+ compare_from = timeCompare(&leaf_valid_from, &cert->valid_from);
+ compare_until = timeCompare(&leaf_valid_from, &cert->valid_to);
+ VerifyOrExit((compare_from >= 0) && (compare_until <= 0),
+ (result = CertificateChainValidationResult::kChainInvalid, error = CHIP_ERROR_CERT_NOT_TRUSTED));
+ cert = cert->next;
+ }
+
+ /* Verify the chain against the root */
+ mbedResult = mbedtls_x509_crt_verify(&certChain, &rootCert, NULL, NULL, &flags, NULL, NULL);
+
+ switch (mbedResult)
+ {
+ case 0:
+ VerifyOrExit(flags == 0, (result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL));
+ result = CertificateChainValidationResult::kSuccess;
+ break;
+ case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
+ result = CertificateChainValidationResult::kChainInvalid;
+ error = CHIP_ERROR_CERT_NOT_TRUSTED;
+ break;
+ default:
+ SuccessOrExit((result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL));
+ }
+
+exit:
+ _log_mbedTLS_error(mbedResult);
+ mbedtls_x509_crt_free(&certChain);
+ mbedtls_x509_crt_free(&rootCert);
+
+#else
+ (void) rootCertificate;
+ (void) rootCertificateLen;
+ (void) caCertificate;
+ (void) caCertificateLen;
+ (void) leafCertificate;
+ (void) leafCertificateLen;
+ (void) result;
+ CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+ return error;
+}
+
+inline bool IsTimeGreaterThanEqual(const mbedtls_x509_time * const timeA, const mbedtls_x509_time * const timeB)
+{
+
+ // checks if two values are different and if yes, then returns first > second.
+#define RETURN_STRICTLY_GREATER_IF_DIFFERENT(component) \
+ { \
+ auto valueA = timeA->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \
+ auto valueB = timeB->CHIP_CRYPTO_PAL_PRIVATE_X509(component); \
+ \
+ if (valueA != valueB) \
+ { \
+ return valueA > valueB; \
+ } \
+ }
+
+ RETURN_STRICTLY_GREATER_IF_DIFFERENT(year);
+ RETURN_STRICTLY_GREATER_IF_DIFFERENT(mon);
+ RETURN_STRICTLY_GREATER_IF_DIFFERENT(day);
+ RETURN_STRICTLY_GREATER_IF_DIFFERENT(hour);
+ RETURN_STRICTLY_GREATER_IF_DIFFERENT(min);
+ RETURN_STRICTLY_GREATER_IF_DIFFERENT(sec);
+
+ // all above are equal
+ return true;
+}
+
+CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & referenceCertificate, const ByteSpan & toBeEvaluatedCertificate)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ mbedtls_x509_crt mbedReferenceCertificate;
+ mbedtls_x509_crt mbedToBeEvaluatedCertificate;
+ mbedtls_x509_time refNotBeforeTime;
+ mbedtls_x509_time tbeNotBeforeTime;
+ mbedtls_x509_time tbeNotAfterTime;
+ int result;
+
+ VerifyOrReturnError(!referenceCertificate.empty() && !toBeEvaluatedCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT);
+
+ mbedtls_x509_crt_init(&mbedReferenceCertificate);
+ mbedtls_x509_crt_init(&mbedToBeEvaluatedCertificate);
+
+ result = mbedtls_x509_crt_parse(&mbedReferenceCertificate, Uint8::to_const_uchar(referenceCertificate.data()),
+ referenceCertificate.size());
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ result = mbedtls_x509_crt_parse(&mbedToBeEvaluatedCertificate, Uint8::to_const_uchar(toBeEvaluatedCertificate.data()),
+ toBeEvaluatedCertificate.size());
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ refNotBeforeTime = mbedReferenceCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from);
+ tbeNotBeforeTime = mbedToBeEvaluatedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from);
+ tbeNotAfterTime = mbedToBeEvaluatedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to);
+
+ // check if referenceCertificate is issued at or after tbeCertificate's notBefore timestamp
+ VerifyOrExit(IsTimeGreaterThanEqual(&refNotBeforeTime, &tbeNotBeforeTime), error = CHIP_ERROR_CERT_EXPIRED);
+
+ // check if referenceCertificate is issued at or before tbeCertificate's notAfter timestamp
+ VerifyOrExit(IsTimeGreaterThanEqual(&tbeNotAfterTime, &refNotBeforeTime), error = CHIP_ERROR_CERT_EXPIRED);
+
+exit:
+ _log_mbedTLS_error(result);
+ mbedtls_x509_crt_free(&mbedReferenceCertificate);
+ mbedtls_x509_crt_free(&mbedToBeEvaluatedCertificate);
+
+#else
+ (void) referenceCertificate;
+ (void) toBeEvaluatedCertificate;
+ CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+ return error;
+}
+
+CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ mbedtls_x509_crt mbedCertificate;
+ int result;
+
+ VerifyOrReturnError(!certificate.empty(), CHIP_ERROR_INVALID_ARGUMENT);
+
+ mbedtls_x509_crt_init(&mbedCertificate);
+
+ result = mbedtls_x509_crt_parse(&mbedCertificate, Uint8::to_const_uchar(certificate.data()), certificate.size());
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // check if certificate's notBefore timestamp is earlier than or equal to current time.
+ result = mbedtls_x509_time_is_past(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from));
+ VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
+
+ // check if certificate's notAfter timestamp is later than current time.
+ result = mbedtls_x509_time_is_future(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to));
+ VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
+
+exit:
+ _log_mbedTLS_error(result);
+ mbedtls_x509_crt_free(&mbedCertificate);
+
+#else
+ (void) certificate;
+ CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+ return error;
+}
+
+CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ mbedtls_x509_crt mbed_cert;
+ mbedtls_ecp_keypair * keypair = nullptr;
+ size_t pubkey_size = 0;
+
+ mbedtls_x509_crt_init(&mbed_cert);
+
+ int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(mbedtls_pk_get_type(&(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk))) == MBEDTLS_PK_ECKEY,
+ error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ keypair = mbedtls_pk_ec(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk));
+ VerifyOrExit(keypair->CHIP_CRYPTO_PAL_PRIVATE(grp).id == MapECPGroupId(pubkey.Type()), error = CHIP_ERROR_INVALID_ARGUMENT);
+ // Copy the public key from the cert in raw point format
+ result =
+ mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q),
+ MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey.Bytes()), pubkey.Length());
+
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+ mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+ (void) certificate;
+ (void) pubkey;
+ CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+ return error;
+}
+
+namespace {
+
+CHIP_ERROR ExtractKIDFromX509Cert(bool extractSKID, const ByteSpan & certificate, MutableByteSpan & kid)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ CHIP_ERROR error = CHIP_ERROR_NOT_FOUND;
+ mbedtls_x509_crt mbed_cert;
+ unsigned char * p = nullptr;
+ const unsigned char * end = nullptr;
+ size_t len = 0;
+
+ mbedtls_x509_crt_init(&mbed_cert);
+
+ int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // TODO: The mbedTLS team is working on supporting SKID and AKID extensions processing.
+ // Once it is supported, this code should be updated.
+
+ p = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
+ end = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p) +
+ mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+ while (p < end)
+ {
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+ mbedtls_x509_buf extOID = { MBEDTLS_ASN1_OID, len, p };
+ bool extractCurrentExtSKID = extractSKID && OID_CMP(sOID_Extension_SubjectKeyIdentifier, extOID);
+ bool extractCurrentExtAKID = !extractSKID && OID_CMP(sOID_Extension_AuthorityKeyIdentifier, extOID);
+ p += len;
+
+ int is_critical = 0;
+ result = mbedtls_asn1_get_bool(&p, end, &is_critical);
+ VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+ if (extractCurrentExtSKID || extractCurrentExtAKID)
+ {
+ if (extractCurrentExtSKID)
+ {
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+ }
+ else
+ {
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+ result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+ // Other optional fields, authorityCertIssuer and authorityCertSerialNumber,
+ // will be skipped if present.
+ }
+ VerifyOrExit(len == kSubjectKeyIdentifierLength, error = CHIP_ERROR_WRONG_CERT_TYPE);
+ VerifyOrExit(len <= kid.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
+ memcpy(kid.data(), p, len);
+ if (kid.size() > len)
+ {
+ kid.reduce_size(len);
+ }
+ ExitNow(error = CHIP_NO_ERROR);
+ break;
+ }
+ p += len;
+ }
+
+exit:
+ _log_mbedTLS_error(result);
+ mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+ (void) certificate;
+ (void) kid;
+ CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+ return error;
+}
+
+} // namespace
+
+CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid)
+{
+ return ExtractKIDFromX509Cert(true, certificate, skid);
+}
+
+CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid)
+{
+ return ExtractKIDFromX509Cert(false, certificate, akid);
+}
+
+CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ mbedtls_x509_crt mbed_cert;
+ mbedtls_asn1_named_data * dnIterator = nullptr;
+ AttestationCertVidPid vidpidFromCN;
+
+ mbedtls_x509_crt_init(&mbed_cert);
+
+ int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ for (dnIterator = &mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(subject); dnIterator != nullptr;
+ dnIterator = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(next))
+ {
+ DNAttrType attrType = DNAttrType::kUnspecified;
+ if (OID_CMP(sOID_AttributeType_CommonName, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid)))
+ {
+ attrType = DNAttrType::kCommonName;
+ }
+ else if (OID_CMP(sOID_AttributeType_MatterVendorId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid)))
+ {
+ attrType = DNAttrType::kMatterVID;
+ }
+ else if (OID_CMP(sOID_AttributeType_MatterProductId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid)))
+ {
+ attrType = DNAttrType::kMatterPID;
+ }
+
+ size_t val_len = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
+ uint8_t * val_p = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
+ error = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(val_p, val_len), vidpid, vidpidFromCN);
+ SuccessOrExit(error);
+ }
+
+ // If Matter Attributes were not found use values extracted from the CN Attribute,
+ // which might be uninitialized as well.
+ if (!vidpid.Initialized())
+ {
+ vidpid = vidpidFromCN;
+ }
+
+exit:
+ _log_mbedTLS_error(result);
+ mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+ (void) certificate;
+ (void) vidpid;
+ CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+ return error;
+}
+
+} // namespace Crypto
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/ConfigurationManagerImpl.cpp b/src/platform/silabs/SiWx917/ConfigurationManagerImpl.cpp
new file mode 100644
index 0000000..aad7493
--- /dev/null
+++ b/src/platform/silabs/SiWx917/ConfigurationManagerImpl.cpp
@@ -0,0 +1,317 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Nest Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides the implementation of the Device Layer ConfigurationManager object
+ * for EFR32 platforms using the Silicon Labs SDK.
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/internal/GenericConfigurationManagerImpl.ipp>
+
+#include <platform/ConfigurationManager.h>
+#include <platform/DiagnosticDataProvider.h>
+#include <platform/silabs/SilabsConfig.h>
+
+#include "em_rmu.h"
+
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+#include "wfx_host_events.h"
+#endif
+
+namespace chip {
+namespace DeviceLayer {
+
+using namespace ::chip::DeviceLayer::Internal;
+
+ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance()
+{
+ static ConfigurationManagerImpl sInstance;
+ return sInstance;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::Init()
+{
+ CHIP_ERROR err;
+
+ // Initialize the generic implementation base class.
+ err = Internal::GenericConfigurationManagerImpl<SILABSConfig>::Init();
+ SuccessOrExit(err);
+
+ // TODO: Initialize the global GroupKeyStore object here (#1626)
+
+ IncreaseBootCount();
+ // It is possible to configure the possible reset sources with RMU_ResetControl
+ // In this case, we keep Reset control at default setting
+ rebootCause = RMU_ResetCauseGet();
+ RMU_ResetCauseClear();
+
+ err = CHIP_NO_ERROR;
+
+exit:
+ return err;
+}
+
+bool ConfigurationManagerImpl::CanFactoryReset()
+{
+ // TODO: query the application to determine if factory reset is allowed.
+ return true;
+}
+
+void ConfigurationManagerImpl::InitiateFactoryReset()
+{
+ PlatformMgr().ScheduleWork(DoFactoryReset);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount)
+{
+ return SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_BootCount, rebootCount);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::IncreaseBootCount(void)
+{
+ uint32_t bootCount = 0;
+
+ if (SILABSConfig::ConfigValueExists(SILABSConfig::kConfigKey_BootCount))
+ {
+ GetRebootCount(bootCount);
+ }
+
+ return SILABSConfig::WriteConfigValue(SILABSConfig::kConfigKey_BootCount, bootCount + 1);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetBootReason(uint32_t & bootReason)
+{
+ // rebootCause is obtained at bootup.
+ BootReasonType matterBootCause;
+#if defined(_SILICON_LABS_32B_SERIES_1)
+ if (rebootCause & RMU_RSTCAUSE_PORST || rebootCause & RMU_RSTCAUSE_EXTRST) // PowerOn or External pin reset
+ {
+ matterBootCause = BootReasonType::kPowerOnReboot;
+ }
+ else if (rebootCause & RMU_RSTCAUSE_AVDDBOD || rebootCause & RMU_RSTCAUSE_DVDDBOD || rebootCause & RMU_RSTCAUSE_DECBOD)
+ {
+ matterBootCause = BootReasonType::kBrownOutReset;
+ }
+ else if (rebootCause & RMU_RSTCAUSE_SYSREQRST)
+ {
+ matterBootCause = BootReasonType::kSoftwareReset;
+ }
+ else if (rebootCause & RMU_RSTCAUSE_WDOGRST)
+ {
+ matterBootCause = BootReasonType::kSoftwareWatchdogReset;
+ }
+ else
+ {
+ matterBootCause = BootReasonType::kUnspecified;
+ }
+ // Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
+#elif defined(_SILICON_LABS_32B_SERIES_2)
+ if (rebootCause & EMU_RSTCAUSE_POR || rebootCause & EMU_RSTCAUSE_PIN) // PowerOn or External pin reset
+ {
+ matterBootCause = BootReasonType::kPowerOnReboot;
+ }
+ else if (rebootCause & EMU_RSTCAUSE_AVDDBOD || rebootCause & EMU_RSTCAUSE_DVDDBOD || rebootCause & EMU_RSTCAUSE_DECBOD ||
+ rebootCause & EMU_RSTCAUSE_VREGIN || rebootCause & EMU_RSTCAUSE_IOVDD0BOD || rebootCause & EMU_RSTCAUSE_DVDDLEBOD)
+ {
+ matterBootCause = BootReasonType::kBrownOutReset;
+ }
+ else if (rebootCause & EMU_RSTCAUSE_SYSREQ)
+ {
+ matterBootCause = BootReasonType::kSoftwareReset;
+ }
+ else if (rebootCause & EMU_RSTCAUSE_WDOG0 || rebootCause & EMU_RSTCAUSE_WDOG1)
+ {
+ matterBootCause = BootReasonType::kSoftwareWatchdogReset;
+ }
+ else
+ {
+ matterBootCause = BootReasonType::kUnspecified;
+ }
+ // Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
+#else
+ matterBootCause = BootReasonType::kUnspecified;
+#endif
+
+ bootReason = to_underlying(matterBootCause);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
+{
+ if (!SILABSConfig::ConfigValueExists(SILABSConfig::kConfigKey_TotalOperationalHours))
+ {
+ totalOperationalHours = 0;
+ return CHIP_NO_ERROR;
+ }
+
+ return SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_TotalOperationalHours, totalOperationalHours);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours)
+{
+ return SILABSConfig::WriteConfigValue(SILABSConfig::kConfigKey_TotalOperationalHours, totalOperationalHours);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey,
+ uint32_t & value)
+{
+ // This method reads CHIP Persisted Counter type nvm3 objects.
+ // (where persistedStorageKey represents an index to the counter).
+ CHIP_ERROR err;
+
+ err = SILABSConfig::ReadConfigValueCounter(persistedStorageKey, value);
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ }
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey,
+ uint32_t value)
+{
+ // This method reads CHIP Persisted Counter type nvm3 objects.
+ // (where persistedStorageKey represents an index to the counter).
+ CHIP_ERROR err;
+
+ err = SILABSConfig::WriteConfigValueCounter(persistedStorageKey, value);
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ }
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, bool & val)
+{
+ return SILABSConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint32_t & val)
+{
+ return SILABSConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint64_t & val)
+{
+ return SILABSConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
+{
+ return SILABSConfig::ReadConfigValueStr(key, buf, bufSize, outLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
+{
+ return SILABSConfig::ReadConfigValueBin(key, buf, bufSize, outLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, bool val)
+{
+ return SILABSConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint32_t val)
+{
+ return SILABSConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint64_t val)
+{
+ return SILABSConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str)
+{
+ return SILABSConfig::WriteConfigValueStr(key, str);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str, size_t strLen)
+{
+ return SILABSConfig::WriteConfigValueStr(key, str, strLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
+{
+ return SILABSConfig::WriteConfigValueBin(key, data, dataLen);
+}
+
+void ConfigurationManagerImpl::RunConfigUnitTest(void)
+{
+ SILABSConfig::RunConfigUnitTest();
+}
+
+void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg)
+{
+ CHIP_ERROR err;
+
+ ChipLogProgress(DeviceLayer, "Performing factory reset");
+
+ err = SILABSConfig::FactoryResetConfig();
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", chip::ErrorStr(err));
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+
+ ChipLogProgress(DeviceLayer, "Clearing Thread provision");
+ ThreadStackMgr().ErasePersistentInfo();
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
+
+ PersistedStorage::KeyValueStoreMgrImpl().ErasePartition();
+
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+ ChipLogProgress(DeviceLayer, "Clearing WiFi provision");
+ wfx_clear_wifi_provision();
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+
+ // Restart the system.
+ ChipLogProgress(DeviceLayer, "System restarting");
+ NVIC_SystemReset();
+}
+
+#ifdef SL_WIFI
+CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf)
+{
+ sl_wfx_mac_address_t macaddr;
+ wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &macaddr);
+ memcpy(buf, &macaddr.octet[0], sizeof(macaddr.octet));
+
+ return CHIP_NO_ERROR;
+}
+#endif
+
+ConfigurationManager & ConfigurationMgrImpl()
+{
+ return ConfigurationManagerImpl::GetDefaultInstance();
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/ConnectivityManagerImpl.cpp b/src/platform/silabs/SiWx917/ConnectivityManagerImpl.cpp
new file mode 100644
index 0000000..c38a5e5
--- /dev/null
+++ b/src/platform/silabs/SiWx917/ConnectivityManagerImpl.cpp
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Nest Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <platform/ConnectivityManager.h>
+#include <platform/internal/BLEManager.h>
+
+#include <platform/internal/GenericConnectivityManagerImpl_UDP.ipp>
+
+#if INET_CONFIG_ENABLE_TCP_ENDPOINT
+#include <platform/internal/GenericConnectivityManagerImpl_TCP.ipp>
+#endif
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+#include <platform/internal/GenericConnectivityManagerImpl_BLE.ipp>
+#endif
+
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+#include <platform/internal/GenericConnectivityManagerImpl_Thread.ipp>
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::System;
+using namespace ::chip::TLV;
+using namespace ::chip::DeviceLayer::Internal;
+
+namespace chip {
+namespace DeviceLayer {
+
+ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
+
+CHIP_ERROR ConnectivityManagerImpl::_Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ // Initialize the generic base classes that require it.
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+ GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_Init();
+#endif
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
+{
+ // Forward the event to the generic base classes as needed.
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+ GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_OnPlatformEvent(event);
+#endif
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32OpaqueKeypair.h b/src/platform/silabs/SiWx917/Efr32OpaqueKeypair.h
new file mode 100644
index 0000000..58123c1
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32OpaqueKeypair.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <crypto/CHIPCryptoPAL.h>
+#include <platform/CHIPDeviceError.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+typedef uint16_t EFR32OpaqueKeyId;
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdUnknown = 0xFFFFU; // Do not modify, will impact existing deployments
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdVolatile = 0xFFFEU; // Do not modify, will impact existing deployments
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdPersistentMin = 0x0U; // Do not modify, will impact existing deployments
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdPersistentMax = 0x1FFU; // Do not decrease, will impact existing deployments
+
+enum class EFR32OpaqueKeyUsages : uint8_t
+{
+ ECDSA_P256_SHA256 = 0,
+ ECDH_P256 = 1,
+};
+
+/**
+ * @brief Base class for opaque keys
+ *
+ * Deriving from this class allows using it as a base class for operations
+ * which don't expose the private key independent of key size.
+ **/
+class EFR32OpaqueKeypair
+{
+public:
+ EFR32OpaqueKeypair();
+ virtual ~EFR32OpaqueKeypair();
+
+ /**
+ * @brief Load a keypair with given key ID
+ *
+ * If no key exists under the given ID, an error is returned
+ * and the object is unusable for operations.
+ *
+ * @param key_id key ID under which this key was created
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Load(EFR32OpaqueKeyId key_id);
+
+ /**
+ * @brief Create a new keypair with given ID and usage
+ *
+ * If a key already exists under the given ID, an error is returned
+ * and no new key is created.
+ *
+ * @param key_id key ID under which to store this key. Set to 0
+ * for a non-persistent key which gets destructed
+ * when the lifetime of this object ends, or set
+ * to any other value to store the key under that
+ * ID.
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Create(EFR32OpaqueKeyId key_id, EFR32OpaqueKeyUsages usage);
+
+ /**
+ * @brief Get the public key for this keypair
+ *
+ * @param output Output buffer to put public key (in 0x04 || X || Y format)
+ * @param output_size Size of \p output
+ * @param output_length Amount of bytes put in \p output on success
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR GetPublicKey(uint8_t * output, size_t output_size, size_t * output_length) const;
+
+ /**
+ * @brief Get the key ID for this keypair
+ *
+ * @return Returns kEFR32OpaqueKeyIdUnknown for an uninitialised/invalid
+ * key, kEFR32OpaqueKeyIdVolatile for a volatile key, and a key
+ * ID in the range [kEFR32OpaqueKeyIdPersistentMin, kEFR32OpaqueKeyIdPersistentMax]
+ * for valid persistent keys.
+ **/
+ EFR32OpaqueKeyId GetKeyId() const;
+
+ /**
+ * @brief Use this keypair to sign a message using the ECDSA-SHA256 algorithm
+ *
+ * @param msg Message buffer to sign
+ * @param msg_len Size of \p msg in bytes
+ * @param output Output buffer to write signature to. Signature
+ * is in raw format (i.e. binary concatenation of
+ * r and s)
+ * @param output_size Size of output buffer
+ * @param output_length Amount of bytes written into output buffer
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Sign(const uint8_t * msg, size_t msg_len, uint8_t * output, size_t output_size, size_t * output_length) const;
+
+ /**
+ * @brief Use this keypair to derive a key using the raw ECDH algorithm
+ *
+ * @param their_key Buffer containing raw uncompressed public key
+ * of party to derive with
+ * @param their_key_len Size of \p their_key in bytes
+ * @param output Output buffer to write derived bytes to
+ * @param output_size Size of output buffer
+ * @param output_length Amount of bytes written into output buffer
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Derive(const uint8_t * their_key, size_t their_key_len, uint8_t * output, size_t output_size,
+ size_t * output_length) const;
+
+ /**
+ * @brief Delete the keypair from storage
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Delete();
+
+protected:
+ void * mContext = nullptr;
+ bool mHasKey = false;
+ bool mIsPersistent = false;
+ uint8_t * mPubkeyRef = nullptr;
+ size_t mPubkeySize = 0;
+ size_t mPubkeyLength = 0;
+};
+
+/**
+ * @brief Derived class of P256Keypair for using opaque keys
+ *
+ * The signature and compiled form of this class is suboptimal due to how
+ * the P256Keypair isn't really an abstract interface, but rather partly
+ * interface / partly implementation. Future optimisation should look at
+ * converting P256Keypair to a fully abstract interface.
+ **/
+class EFR32OpaqueP256Keypair : public chip::Crypto::P256Keypair, public EFR32OpaqueKeypair
+{
+public:
+ EFR32OpaqueP256Keypair();
+ ~EFR32OpaqueP256Keypair() override;
+
+ /**
+ * @brief Initialize the keypair.
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Initialize() override;
+
+ /**
+ * @brief Serialize the keypair (unsupported on opaque keys)
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Serialize(chip::Crypto::P256SerializedKeypair & output) const override;
+
+ /**
+ * @brief Deserialize the keypair (unsupported on opaque keys)
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Deserialize(chip::Crypto::P256SerializedKeypair & input) override;
+
+ /**
+ * @brief Generate a new Certificate Signing Request (CSR).
+ * @param csr Newly generated CSR in DER format
+ * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
+ *CSR.
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const override;
+
+ /**
+ * @brief A function to sign a msg using ECDSA
+ * @param msg Message that needs to be signed
+ * @param msg_length Length of message
+ * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
+ * in raw <r,s> point form (see SEC1).
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length,
+ chip::Crypto::P256ECDSASignature & out_signature) const override;
+
+ /**
+ * @brief A function to derive a shared secret using ECDH
+ *
+ * This implements the CHIP_Crypto_ECDH(PrivateKey myPrivateKey, PublicKey theirPublicKey) cryptographic primitive
+ * from the specification, using this class's private key from `mKeypair` as `myPrivateKey` and the remote
+ * public key from `remote_public_key` as `theirPublicKey`.
+ *
+ * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
+ * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
+ * [https://www.secg.org/sec1-v2.pdf]
+ * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR ECDH_derive_secret(const chip::Crypto::P256PublicKey & remote_public_key,
+ chip::Crypto::P256ECDHDerivedSecret & out_secret) const override;
+
+ /** @brief Return public key for the keypair.
+ **/
+ const chip::Crypto::P256PublicKey & Pubkey() const override;
+
+private:
+ chip::Crypto::P256PublicKey mPubKey;
+};
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32PsaOpaqueKeypair.cpp b/src/platform/silabs/SiWx917/Efr32PsaOpaqueKeypair.cpp
new file mode 100644
index 0000000..ae9a0f6
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32PsaOpaqueKeypair.cpp
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Efr32OpaqueKeypair.h"
+#include "em_device.h"
+#include <psa/crypto.h>
+
+#include <lib/core/CHIPSafeCasts.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/SafeInt.h>
+using chip::Platform::MemoryCalloc;
+using chip::Platform::MemoryFree;
+
+using chip::Crypto::P256ECDHDerivedSecret;
+using chip::Crypto::P256ECDSASignature;
+using chip::Crypto::P256Keypair;
+using chip::Crypto::P256PublicKey;
+using chip::Crypto::P256SerializedKeypair;
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+/*******************************************************************************
+ *
+ * PSA key ID range for storing Matter Opaque keys
+ *
+ ******************************************************************************/
+#define PSA_KEY_ID_FOR_MATTER_MIN (0x00004400)
+#define PSA_KEY_ID_FOR_MATTER_MAX (0x000045FF)
+#define PSA_KEY_ID_FOR_MATTER_SIZE (PSA_KEY_ID_FOR_MATTER_MAX - PSA_KEY_ID_FOR_MATTER_MIN + 1)
+
+static_assert((kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin) < PSA_KEY_ID_FOR_MATTER_SIZE,
+ "Not enough PSA range to store all allowed opaque key IDs");
+
+#if defined(SEMAILBOX_PRESENT) && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
+#define PSA_CRYPTO_LOCATION_FOR_DEVICE PSA_KEY_LOCATION_SL_SE_OPAQUE
+#elif defined(CRYPTOACC_PRESENT) && defined(SEPUF_PRESENT) && defined(SL_TRUSTZONE_NONSECURE)
+#define PSA_CRYPTO_LOCATION_FOR_DEVICE PSA_KEY_LOCATION_SL_CRYPTOACC_OPAQUE
+#else
+#define PSA_CRYPTO_LOCATION_FOR_DEVICE PSA_KEY_LOCATION_LOCAL_STORAGE
+#endif
+
+static void _log_PSA_error(psa_status_t status)
+{
+ if (status != PSA_SUCCESS)
+ {
+ ChipLogError(Crypto, "PSA error: %ld", status);
+ }
+}
+
+/*******************************************************************************
+ *
+ * PSA Crypto backed implementation of EFR32OpaqueKeypair
+ *
+ ******************************************************************************/
+
+static bool is_opaque_key_valid(EFR32OpaqueKeyId id)
+{
+ if (id == kEFR32OpaqueKeyIdVolatile)
+ {
+ return true;
+ }
+ else if (id >= kEFR32OpaqueKeyIdPersistentMin && id <= (kEFR32OpaqueKeyIdPersistentMin + PSA_KEY_ID_FOR_MATTER_SIZE))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+static mbedtls_svc_key_id_t psa_key_id_from_opaque(EFR32OpaqueKeyId id)
+{
+ if (id == kEFR32OpaqueKeyIdVolatile || !is_opaque_key_valid(id))
+ {
+ return 0;
+ }
+
+ return PSA_KEY_ID_FOR_MATTER_MIN + (id - kEFR32OpaqueKeyIdPersistentMin);
+}
+
+static EFR32OpaqueKeyId opaque_key_id_from_psa(mbedtls_svc_key_id_t id)
+{
+ if (id == 0)
+ {
+ return kEFR32OpaqueKeyIdVolatile;
+ }
+ else if (id >= PSA_KEY_ID_FOR_MATTER_MIN && id <= PSA_KEY_ID_FOR_MATTER_MAX)
+ {
+ return (id + kEFR32OpaqueKeyIdPersistentMin) - PSA_KEY_ID_FOR_MATTER_MIN;
+ }
+ else
+ {
+ return kEFR32OpaqueKeyIdUnknown;
+ }
+}
+
+EFR32OpaqueKeypair::EFR32OpaqueKeypair()
+{
+ psa_crypto_init();
+ // Avoid having a reference to PSA datatypes in the signature of this class
+ mContext = MemoryCalloc(1, sizeof(mbedtls_svc_key_id_t));
+}
+
+EFR32OpaqueKeypair::~EFR32OpaqueKeypair()
+{
+ // Free key resources
+ if (mContext != nullptr)
+ {
+ // Delete volatile keys, since nobody else can after we drop the key ID.
+ if (!mIsPersistent)
+ {
+ Delete();
+ }
+
+ MemoryFree(mContext);
+ mContext = nullptr;
+ }
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Load(EFR32OpaqueKeyId opaque_id)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ mbedtls_svc_key_id_t key_id = 0;
+
+ VerifyOrExit(opaque_id != kEFR32OpaqueKeyIdVolatile, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(is_opaque_key_valid(opaque_id), error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(mContext, error = CHIP_ERROR_INCORRECT_STATE);
+
+ // If the object contains a volatile key, clean it up before reusing the object storage
+ if (mHasKey && !mIsPersistent)
+ {
+ Delete();
+ }
+
+ key_id = psa_key_id_from_opaque(opaque_id);
+
+ status = psa_export_public_key(key_id, mPubkeyRef, mPubkeySize, &mPubkeyLength);
+
+ if (status == PSA_ERROR_DOES_NOT_EXIST)
+ {
+ error = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
+ goto exit;
+ }
+
+ VerifyOrExit(status == PSA_SUCCESS, {
+ _log_PSA_error(status);
+ error = CHIP_ERROR_INTERNAL;
+ });
+
+ // Store the key ID and mark the key as valid
+ *(mbedtls_svc_key_id_t *) mContext = key_id;
+ mHasKey = true;
+ mIsPersistent = true;
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ memset(mPubkeyRef, 0, mPubkeySize);
+ }
+
+ return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Create(EFR32OpaqueKeyId opaque_id, EFR32OpaqueKeyUsages usage)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ mbedtls_svc_key_id_t key_id = 0;
+
+ VerifyOrExit(is_opaque_key_valid(opaque_id), error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(mContext, error = CHIP_ERROR_INCORRECT_STATE);
+
+ if (opaque_id == kEFR32OpaqueKeyIdVolatile)
+ {
+ psa_set_key_lifetime(
+ &attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE, PSA_CRYPTO_LOCATION_FOR_DEVICE));
+ }
+ else
+ {
+ psa_key_handle_t key_handle;
+
+ key_id = psa_key_id_from_opaque(opaque_id);
+
+ // Check if the key already exists
+ int ret = psa_open_key(key_id, &key_handle);
+ if (PSA_SUCCESS == ret)
+ {
+ // WARNING: Existing key! This is caused by a problem in the key store.
+ // The key must be destroyed, otherwhise the device won't recover.
+ ChipLogError(Crypto, "WARNING: PSA key recycled: %d / %ld", opaque_id, key_id);
+ psa_destroy_key(key_id);
+ }
+
+ psa_set_key_id(&attr, key_id);
+ psa_set_key_lifetime(
+ &attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_PERSISTENT, PSA_CRYPTO_LOCATION_FOR_DEVICE));
+ }
+
+ switch (usage)
+ {
+ case EFR32OpaqueKeyUsages::ECDSA_P256_SHA256:
+ psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attr, 256);
+ psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+ // Need hash signing permissions because the CSR generation uses sign_hash internally
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_SIGN_HASH);
+ break;
+ case EFR32OpaqueKeyUsages::ECDH_P256:
+ psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+ psa_set_key_bits(&attr, 256);
+ psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
+ psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
+ break;
+ }
+
+ status = psa_generate_key(&attr, &key_id);
+ VerifyOrExit(status == PSA_SUCCESS, {
+ _log_PSA_error(status);
+ error = CHIP_ERROR_INTERNAL;
+ });
+
+ // Export the public key
+ status = psa_export_public_key(key_id, mPubkeyRef, mPubkeySize, &mPubkeyLength);
+ if (PSA_SUCCESS != status)
+ {
+ _log_PSA_error(status);
+ // Key generation succeeded, but pubkey export did not. To avoid
+ // memory leaks, delete the generated key before returning the error
+ psa_destroy_key(key_id);
+ error = CHIP_ERROR_INTERNAL;
+ goto exit;
+ }
+
+ // Store the key ID and mark the key as valid
+ mHasKey = true;
+ mIsPersistent = opaque_id != kEFR32OpaqueKeyIdVolatile;
+
+exit:
+ psa_reset_key_attributes(&attr);
+ if (mContext)
+ {
+ if (CHIP_NO_ERROR == error)
+ {
+ *(mbedtls_svc_key_id_t *) mContext = key_id;
+ }
+ else
+ {
+ *(mbedtls_svc_key_id_t *) mContext = 0;
+ }
+ }
+ return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::GetPublicKey(uint8_t * output, size_t output_size, size_t * output_length) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+ if (output_size >= mPubkeyLength)
+ {
+ memcpy(output, mPubkeyRef, mPubkeyLength);
+ *output_length = mPubkeyLength;
+ }
+ else
+ {
+ error = CHIP_ERROR_BUFFER_TOO_SMALL;
+ }
+exit:
+ return error;
+}
+
+EFR32OpaqueKeyId EFR32OpaqueKeypair::GetKeyId() const
+{
+ if (!mHasKey)
+ {
+ return kEFR32OpaqueKeyIdUnknown;
+ }
+
+ if (!mIsPersistent)
+ {
+ return kEFR32OpaqueKeyIdVolatile;
+ }
+
+ return opaque_key_id_from_psa(*(mbedtls_svc_key_id_t *) mContext);
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Sign(const uint8_t * msg, size_t msg_len, uint8_t * output, size_t output_size,
+ size_t * output_length) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+
+ VerifyOrExit(mContext, error = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+ status = psa_sign_message(*(mbedtls_svc_key_id_t *) mContext, PSA_ALG_ECDSA(PSA_ALG_SHA_256), msg, msg_len, output, output_size,
+ output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, {
+ _log_PSA_error(status);
+ error = CHIP_ERROR_INTERNAL;
+ });
+
+exit:
+ return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Derive(const uint8_t * their_key, size_t their_key_len, uint8_t * output, size_t output_size,
+ size_t * output_length) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+
+ VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+ status = psa_raw_key_agreement(PSA_ALG_ECDH, *(mbedtls_svc_key_id_t *) mContext, their_key, their_key_len, output, output_size,
+ output_length);
+
+ VerifyOrExit(status == PSA_SUCCESS, {
+ _log_PSA_error(status);
+ error = CHIP_ERROR_INTERNAL;
+ });
+
+exit:
+ return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Delete()
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+
+ VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+ status = psa_destroy_key(*(mbedtls_svc_key_id_t *) mContext);
+ VerifyOrExit(status == PSA_SUCCESS, {
+ _log_PSA_error(status);
+ error = CHIP_ERROR_INTERNAL;
+ });
+
+exit:
+ mHasKey = false;
+ mIsPersistent = false;
+ memset(mPubkeyRef, 0, mPubkeySize);
+ if (mContext)
+ {
+ *(mbedtls_svc_key_id_t *) mContext = 0;
+ }
+ return error;
+}
+
+/*******************************************************************************
+ *
+ * PSA Crypto backed implementation of EFR32OpaqueP256Keypair
+ *
+ ******************************************************************************/
+EFR32OpaqueP256Keypair::EFR32OpaqueP256Keypair()
+{
+ mPubkeyRef = mPubKey.Bytes();
+ mPubkeySize = mPubKey.Length();
+ mPubkeyLength = 0;
+}
+
+EFR32OpaqueP256Keypair::~EFR32OpaqueP256Keypair() {}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::Initialize()
+{
+ if (mPubkeyLength > 0)
+ {
+ // already have a key - ECDH use case where CASESession is calling Initialize()
+ return CHIP_NO_ERROR;
+ }
+
+ ChipLogError(Crypto, "Initialize() is invalid on opaque keys, use Create() instead");
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::Serialize(P256SerializedKeypair & output) const
+{
+ ChipLogError(Crypto, "Serialisation is invalid on opaque keys, share the object instead");
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::Deserialize(P256SerializedKeypair & input)
+{
+ ChipLogError(Crypto, "Serialisation is invalid on opaque keys");
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
+{
+ MutableByteSpan csr(out_csr, csr_length);
+ CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr);
+ csr_length = (CHIP_NO_ERROR == err) ? csr.size() : 0;
+ return err;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ size_t output_length = 0;
+
+ VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ error = Sign(msg, msg_length, out_signature.Bytes(), out_signature.Capacity(), &output_length);
+
+ SuccessOrExit(error);
+ SuccessOrExit(out_signature.SetLength(output_length));
+exit:
+ return error;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key,
+ P256ECDHDerivedSecret & out_secret) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ size_t output_length = 0;
+
+ error = Derive(Uint8::to_const_uchar(remote_public_key), remote_public_key.Length(), Uint8::to_uchar(out_secret),
+ (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(), &output_length);
+
+ SuccessOrExit(error);
+ SuccessOrExit(out_secret.SetLength(output_length));
+exit:
+ return error;
+}
+
+const P256PublicKey & EFR32OpaqueP256Keypair::Pubkey() const
+{
+ return mPubKey;
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.cpp b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.cpp
new file mode 100644
index 0000000..e8fdf61
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.cpp
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "Efr32PsaOperationalKeystore.h"
+
+#include <crypto/OperationalKeystore.h>
+#include <lib/core/CHIPError.h>
+#include <lib/core/CHIPTLV.h>
+#include <lib/core/DataModelTypes.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/SafeInt.h>
+
+#include "Efr32OpaqueKeypair.h"
+#include <platform/silabs/SilabsConfig.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+static_assert((sizeof(FabricIndex) == 1), "Implementation is not prepared for large fabric indices");
+static_assert(SL_MATTER_MAX_STORED_OP_KEYS <= (kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin),
+ "Not enough opaque keys available to cover all requested operational keys");
+static_assert((CHIP_CONFIG_MAX_FABRICS + 1) <= SL_MATTER_MAX_STORED_OP_KEYS,
+ "Not enough operational keys requested to cover all potential fabrics (+1 staging for fabric update)");
+static_assert(SL_MATTER_MAX_STORED_OP_KEYS >= 1, "Minimum supported amount of operational keys is 1");
+
+using namespace chip::Crypto;
+
+using chip::Platform::MemoryCalloc;
+using chip::Platform::MemoryFree;
+
+Efr32PsaOperationalKeystore::~Efr32PsaOperationalKeystore()
+{
+ Deinit();
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::Init()
+{
+ // Detect existing keymap size
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ size_t wantedLen = SL_MATTER_MAX_STORED_OP_KEYS * sizeof(FabricIndex);
+ size_t existingLen = 0;
+ bool update_cache = false;
+
+ if (SILABSConfig::ConfigValueExists(SILABSConfig::kConfigKey_OpKeyMap, existingLen))
+ {
+ // There's a pre-existing key map on disk. Size the map to read it fully.
+ size_t outLen = 0;
+
+ if (existingLen > (kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin) * sizeof(FabricIndex))
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ // Upsize the map if the config was changed
+ if (existingLen < wantedLen)
+ {
+ existingLen = wantedLen;
+ }
+
+ mKeyMap = (FabricIndex *) MemoryCalloc(1, existingLen);
+ VerifyOrExit(mKeyMap, error = CHIP_ERROR_NO_MEMORY);
+
+ // Read the existing key map
+ error = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, (uint8_t *) mKeyMap, existingLen, outLen);
+ SuccessOrExit(error);
+
+ // If upsizing, extend the map with undefined indices
+ for (size_t i = (outLen / sizeof(FabricIndex)); i < (existingLen / sizeof(FabricIndex)); i++)
+ {
+ mKeyMap[i] = kUndefinedFabricIndex;
+ }
+
+ // If the config has changed, check whether it can be downsized fully or partially
+ if (existingLen > wantedLen)
+ {
+ size_t highest_found_index = 0;
+ for (size_t i = (wantedLen / sizeof(FabricIndex)); i < (existingLen / sizeof(FabricIndex)); i++)
+ {
+ if (mKeyMap[i] != kUndefinedFabricIndex)
+ {
+ highest_found_index = i;
+ }
+ }
+
+ // set size to the smallest that will fit the upper opaque key ID in use
+ if (highest_found_index > 0)
+ {
+ existingLen = (highest_found_index + 1) * sizeof(FabricIndex);
+ update_cache = true;
+ }
+ }
+
+ // Set the key map size
+ mKeyMapSize = existingLen;
+ }
+ else
+ {
+ // No key map on disk. Create and initialize a new one.
+ mKeyMap = (FabricIndex *) MemoryCalloc(1, wantedLen);
+ VerifyOrExit(mKeyMap, error = CHIP_ERROR_NO_MEMORY);
+
+ for (size_t i = 0; i < (wantedLen / sizeof(FabricIndex)); i++)
+ {
+ mKeyMap[i] = kUndefinedFabricIndex;
+ }
+
+ mKeyMapSize = wantedLen;
+
+ update_cache = true;
+ }
+
+ // Write-out keymap if needed
+ if (update_cache)
+ {
+ error = SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
+ SuccessOrExit(error);
+ }
+
+ // Initialize cache key
+ mCachedKey = Platform::New<EFR32OpaqueP256Keypair>();
+ VerifyOrExit(mCachedKey, error = CHIP_ERROR_NO_MEMORY);
+
+exit:
+ if (error != CHIP_NO_ERROR)
+ {
+ Deinit();
+ return error;
+ }
+
+ mIsInitialized = true;
+ return CHIP_NO_ERROR;
+}
+
+EFR32OpaqueKeyId Efr32PsaOperationalKeystore::FindKeyIdForFabric(FabricIndex fabricIndex) const
+{
+ // Search the map linearly to find a matching index slot
+ for (size_t i = 0; i < (mKeyMapSize / sizeof(FabricIndex)); i++)
+ {
+ if (mKeyMap[i] == fabricIndex)
+ {
+ // Found a match
+ return i + kEFR32OpaqueKeyIdPersistentMin;
+ }
+ }
+
+ return kEFR32OpaqueKeyIdUnknown;
+}
+
+bool Efr32PsaOperationalKeystore::HasOpKeypairForFabric(FabricIndex fabricIndex) const
+{
+ VerifyOrReturnError(mIsInitialized, false);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);
+
+ // If there was a pending keypair, then there's really a usable key
+ if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex) && (mPendingKeypair != nullptr))
+ {
+ return true;
+ }
+
+ // Check whether we have a match in the map
+ if (FindKeyIdForFabric(fabricIndex) != kEFR32OpaqueKeyIdUnknown)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::NewOpKeypairForFabric(FabricIndex fabricIndex,
+ MutableByteSpan & outCertificateSigningRequest)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ // If a key is pending, we cannot generate for a different fabric index until we commit or revert.
+ if ((mPendingFabricIndex != kUndefinedFabricIndex) && (fabricIndex != mPendingFabricIndex))
+ {
+ return CHIP_ERROR_INVALID_FABRIC_INDEX;
+ }
+
+ VerifyOrReturnError(outCertificateSigningRequest.size() >= Crypto::kMAX_CSR_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ // Generate new key
+ EFR32OpaqueKeyId id = kEFR32OpaqueKeyIdUnknown;
+
+ if (mPendingFabricIndex != kUndefinedFabricIndex)
+ {
+ // If we already have a pending key, delete it and put a new one in its place
+ id = mPendingKeypair->GetKeyId();
+ if (id == kEFR32OpaqueKeyIdUnknown)
+ {
+ ResetPendingKey();
+ }
+ else
+ {
+ mPendingKeypair->Delete();
+ if (id == kEFR32OpaqueKeyIdVolatile)
+ {
+ id = kEFR32OpaqueKeyIdUnknown;
+ }
+ }
+ }
+
+ if (id == kEFR32OpaqueKeyIdUnknown)
+ {
+ // Try to find an available opaque ID in the map
+ id = FindKeyIdForFabric(kUndefinedFabricIndex);
+
+ if (!mPendingKeypair)
+ {
+ mPendingKeypair = Platform::New<EFR32OpaqueP256Keypair>();
+ }
+ }
+
+ if (id == kEFR32OpaqueKeyIdUnknown)
+ {
+ // Could not find a free spot in the map
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ // Create new key on the old or found key ID
+ error = mPendingKeypair->Create(id, EFR32OpaqueKeyUsages::ECDSA_P256_SHA256);
+ if (error != CHIP_NO_ERROR)
+ {
+ ResetPendingKey();
+ return error;
+ }
+
+ // Set CSR and state
+ size_t csrLength = outCertificateSigningRequest.size();
+ error = mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength);
+ if (error != CHIP_NO_ERROR)
+ {
+ ResetPendingKey();
+ return error;
+ }
+
+ outCertificateSigningRequest.reduce_size(csrLength);
+ mPendingFabricIndex = fabricIndex;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::ActivateOpKeypairForFabric(FabricIndex fabricIndex,
+ const Crypto::P256PublicKey & nocPublicKey)
+{
+ VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ // Validate public key being activated matches last generated pending keypair
+ VerifyOrReturnError(mPendingKeypair->Pubkey().Matches(nocPublicKey), CHIP_ERROR_INVALID_PUBLIC_KEY);
+
+ mIsPendingKeypairActive = true;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::CommitOpKeypairForFabric(FabricIndex fabricIndex)
+{
+ VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(mIsPendingKeypairActive == true, CHIP_ERROR_INCORRECT_STATE);
+
+ // Add key association to key map
+ EFR32OpaqueKeyId id = mPendingKeypair->GetKeyId();
+
+ if (id == kEFR32OpaqueKeyIdUnknown || id == kEFR32OpaqueKeyIdVolatile)
+ {
+ ResetPendingKey();
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ // Guard against array out-of-bounds (should not happen with correctly initialised keys)
+ size_t keymap_index = id - kEFR32OpaqueKeyIdPersistentMin;
+ if (keymap_index >= (mKeyMapSize / sizeof(FabricIndex)))
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ if (mKeyMap[keymap_index] != kUndefinedFabricIndex)
+ {
+ ResetPendingKey();
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ mKeyMap[keymap_index] = fabricIndex;
+
+ // Persist key map
+ CHIP_ERROR error = SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
+ if (error != CHIP_NO_ERROR)
+ {
+ return error;
+ }
+
+ // There's a good chance we'll need the key again soon
+ mCachedKey->Load(id);
+
+ mPendingKeypair = nullptr;
+ mIsPendingKeypairActive = false;
+ mPendingFabricIndex = kUndefinedFabricIndex;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::RemoveOpKeypairForFabric(FabricIndex fabricIndex)
+{
+ VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ // Remove pending keypair if we have it and the fabric ID matches
+ if ((mPendingKeypair != nullptr) && (fabricIndex == mPendingFabricIndex))
+ {
+ RevertPendingKeypair();
+ }
+
+ EFR32OpaqueKeyId id = FindKeyIdForFabric(fabricIndex);
+ if (id == kEFR32OpaqueKeyIdUnknown)
+ {
+ // Fabric is not in the map, so assume it's gone already
+ return CHIP_NO_ERROR;
+ }
+
+ // Guard against array out-of-bounds (should not happen with correctly initialised keys)
+ size_t keymap_index = id - kEFR32OpaqueKeyIdPersistentMin;
+ if (keymap_index >= (mKeyMapSize / sizeof(FabricIndex)))
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ // Reset the key mapping since we'll be deleting this key
+ mKeyMap[keymap_index] = kUndefinedFabricIndex;
+
+ // Persist key map
+ CHIP_ERROR error = SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
+ if (error != CHIP_NO_ERROR)
+ {
+ return error;
+ }
+
+ // Check if key is cached
+ EFR32OpaqueKeyId cachedId = mCachedKey->GetKeyId();
+
+ if (id == cachedId)
+ {
+ // Delete from persistent storage and unload
+ mCachedKey->Delete();
+ return CHIP_NO_ERROR;
+ }
+
+ // Load it for purposes of deletion
+ error = mCachedKey->Load(id);
+ if (error != CHIP_NO_ERROR && error != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ mCachedKey->Delete();
+
+ return CHIP_NO_ERROR;
+}
+
+void Efr32PsaOperationalKeystore::RevertPendingKeypair()
+{
+ if (mIsInitialized)
+ {
+ // Just delete the pending key from storage
+ ResetPendingKey();
+ }
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
+ Crypto::P256ECDSASignature & outSignature) const
+{
+ VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ // Check to see whether the key is an activated pending key
+ if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex))
+ {
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INTERNAL);
+ return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+ }
+
+ // Figure out which key ID we're looking for
+ EFR32OpaqueKeyId id = FindKeyIdForFabric(fabricIndex);
+
+ if (id == kEFR32OpaqueKeyIdUnknown)
+ {
+ // Fabric is not in the map, but the caller thinks it's there?
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ // Check whether we have the key in cache
+ EFR32OpaqueKeyId cachedId = mCachedKey->GetKeyId();
+
+ if (id == cachedId)
+ {
+ return mCachedKey->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+ }
+
+ // If not, we need to recreate from the backend
+ CHIP_ERROR error = mCachedKey->Load(id);
+ if (error != CHIP_NO_ERROR)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ // Sign with retrieved key
+ error = mCachedKey->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+ if (error != CHIP_NO_ERROR)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+Crypto::P256Keypair * Efr32PsaOperationalKeystore::AllocateEphemeralKeypairForCASE()
+{
+ EFR32OpaqueP256Keypair * new_key = Platform::New<EFR32OpaqueP256Keypair>();
+
+ if (new_key != nullptr)
+ {
+ new_key->Create(kEFR32OpaqueKeyIdVolatile, EFR32OpaqueKeyUsages::ECDH_P256);
+ }
+
+ return new_key;
+}
+
+void Efr32PsaOperationalKeystore::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair)
+{
+ Platform::Delete<EFR32OpaqueP256Keypair>((EFR32OpaqueP256Keypair *) keypair);
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.h b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.h
new file mode 100644
index 0000000..4203724
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <crypto/OperationalKeystore.h>
+#include <lib/core/CHIPConfig.h>
+
+#include <psa/crypto.h>
+
+#include "Efr32OpaqueKeypair.h"
+#include <platform/CHIPDeviceLayer.h>
+
+// Set SL_MATTER_MAX_STORED_OP_KEYS to the preferred size of the mapping table
+// between fabric IDs and opaque key indices. It can not be less than
+// CHIP_CONFIG_MAX_FABRICS + 1 (since there would be too few map elements to
+// support all fabrics the application wants to support in addition to an extra
+// pending key), but can be larger in case a consistent on-disk size of the map
+// is required.
+#ifndef SL_MATTER_MAX_STORED_OP_KEYS
+#define SL_MATTER_MAX_STORED_OP_KEYS (CHIP_CONFIG_MAX_FABRICS + 1)
+#endif
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+/**
+ * @brief OperationalKeystore implementation making use of the EFR32 SDK-provided
+ * storage mechanisms to load/store keypairs.
+ *
+ * WARNING: Ensure that any implementation that uses this one as a starting point
+ * DOES NOT have the raw key material (in usable form) passed up/down to
+ * direct storage APIs that may make copies on heap/stack without sanitization.
+ */
+class Efr32PsaOperationalKeystore : public chip::Crypto::OperationalKeystore
+{
+public:
+ Efr32PsaOperationalKeystore(){};
+ virtual ~Efr32PsaOperationalKeystore() override;
+
+ // Non-copyable
+ Efr32PsaOperationalKeystore(Efr32PsaOperationalKeystore const &) = delete;
+ void operator=(Efr32PsaOperationalKeystore const &) = delete;
+
+ /**
+ * @brief Initialize the Operational Keystore
+ */
+ CHIP_ERROR Init();
+
+ bool HasPendingOpKeypair() const override { return (mPendingKeypair != nullptr); }
+
+ bool HasOpKeypairForFabric(FabricIndex fabricIndex) const override;
+ CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override;
+ CHIP_ERROR ActivateOpKeypairForFabric(FabricIndex fabricIndex, const chip::Crypto::P256PublicKey & nocPublicKey) override;
+ CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override;
+ CHIP_ERROR RemoveOpKeypairForFabric(FabricIndex fabricIndex) override;
+ void RevertPendingKeypair() override;
+ CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
+ chip::Crypto::P256ECDSASignature & outSignature) const override;
+ Crypto::P256Keypair * AllocateEphemeralKeypairForCASE() override;
+ void ReleaseEphemeralKeypair(chip::Crypto::P256Keypair * keypair) override;
+
+protected:
+ // The keymap maps PSA Crypto persistent key ID offsets against fabric IDs.
+ // The keymap is persisted in NVM3, and the keys are stored through the PSA
+ // API.
+ FabricIndex * mKeyMap = nullptr;
+ size_t mKeyMapSize = 0;
+
+ // The key cache is to avoid having to reconstruct keys from the storage
+ // backend all the time (since it is rather slow).
+ EFR32OpaqueP256Keypair * mCachedKey = nullptr;
+
+ // This pending fabric index is `kUndefinedFabricIndex` if there isn't a
+ // pending keypair override for a given fabric.
+ FabricIndex mPendingFabricIndex = kUndefinedFabricIndex;
+ EFR32OpaqueP256Keypair * mPendingKeypair = nullptr;
+ bool mIsPendingKeypairActive = false;
+ bool mIsInitialized = false;
+
+private:
+ void ResetPendingKey()
+ {
+ if (mPendingKeypair != nullptr)
+ {
+ mPendingKeypair->Delete();
+ Platform::Delete(mPendingKeypair);
+ }
+ mPendingKeypair = nullptr;
+ mIsPendingKeypairActive = false;
+ mPendingFabricIndex = kUndefinedFabricIndex;
+ }
+
+ void Deinit()
+ {
+ ResetPendingKey();
+
+ if (mCachedKey != nullptr)
+ {
+ Platform::Delete<EFR32OpaqueP256Keypair>(mCachedKey);
+ mCachedKey = nullptr;
+ }
+
+ if (mKeyMap != nullptr)
+ {
+ Platform::MemoryFree(mKeyMap);
+ mKeyMap = nullptr;
+ mKeyMapSize = 0;
+ }
+
+ mIsInitialized = false;
+ }
+
+ /**
+ * @brief Find the opaque key ID stored in the map for a given
+ * fabric ID.
+ *
+ * @param fabricIndex The fabric index to find the opaque key ID for.
+ * Can also be kUndefinedFabricIndex to find the first
+ * unoccupied key ID.
+ *
+ * @return a valid key ID on match, or kEFR32OpaqueKeyIdUnknown if no
+ * match is found.
+ */
+ EFR32OpaqueKeyId FindKeyIdForFabric(FabricIndex fabricIndex) const;
+};
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/KeyValueStoreManagerImpl.cpp b/src/platform/silabs/SiWx917/KeyValueStoreManagerImpl.cpp
new file mode 100644
index 0000000..c752c75
--- /dev/null
+++ b/src/platform/silabs/SiWx917/KeyValueStoreManagerImpl.cpp
@@ -0,0 +1,213 @@
+/*
+ *
+ * Copyright (c) 2021-2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Platform-specific key value storage implementation for SILABS
+ */
+
+#include <lib/support/CHIPMemString.h>
+#include <lib/support/CodeUtils.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/KeyValueStoreManager.h>
+#include <platform/silabs/SilabsConfig.h>
+#include <stdio.h>
+#include <string.h>
+
+using namespace ::chip;
+using namespace ::chip::DeviceLayer::Internal;
+
+#define CONVERT_KEYMAP_INDEX_TO_NVM3KEY(index) (SILABSConfig::kConfigKey_KvsFirstKeySlot + index)
+#define CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key) (nvm3Key - SILABSConfig::kConfigKey_KvsFirstKeySlot)
+
+namespace chip {
+namespace DeviceLayer {
+namespace PersistedStorage {
+
+KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;
+char mKvsStoredKeyString[KeyValueStoreManagerImpl::kMaxEntries][PersistentStorageDelegate::kKeyLengthMax + 1];
+
+CHIP_ERROR KeyValueStoreManagerImpl::Init(void)
+{
+ CHIP_ERROR err;
+ err = SILABSConfig::Init();
+ SuccessOrExit(err);
+
+ memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString));
+ size_t outLen;
+ err = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_KvsStringKeyMap,
+ reinterpret_cast<uint8_t *>(mKvsStoredKeyString), sizeof(mKvsStoredKeyString), outLen);
+
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) // Initial boot
+ {
+ err = CHIP_NO_ERROR;
+ }
+
+exit:
+ return err;
+}
+
+bool KeyValueStoreManagerImpl::IsValidKvsNvm3Key(uint32_t nvm3Key) const
+{
+ return ((SILABSConfig::kConfigKey_KvsFirstKeySlot <= nvm3Key) && (nvm3Key <= SILABSConfig::kConfigKey_KvsLastKeySlot));
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::MapKvsKeyToNvm3(const char * key, uint32_t & nvm3Key, bool isSlotNeeded) const
+{
+ CHIP_ERROR err;
+ uint8_t firstEmptyKeySlot = kMaxEntries;
+ for (uint8_t keyIndex = 0; keyIndex < kMaxEntries; keyIndex++)
+ {
+ if (strcmp(key, mKvsStoredKeyString[keyIndex]) == 0)
+ {
+ nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(keyIndex);
+ VerifyOrDie(IsValidKvsNvm3Key(nvm3Key) == true);
+ return CHIP_NO_ERROR;
+ }
+
+ if (isSlotNeeded && (firstEmptyKeySlot == kMaxEntries) && (mKvsStoredKeyString[keyIndex][0] == 0))
+ {
+ firstEmptyKeySlot = keyIndex;
+ }
+ }
+
+ if (isSlotNeeded)
+ {
+ if (firstEmptyKeySlot != kMaxEntries)
+ {
+ nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(firstEmptyKeySlot);
+ VerifyOrDie(IsValidKvsNvm3Key(nvm3Key) == true);
+ err = CHIP_NO_ERROR;
+ }
+ else
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_FAILED;
+ }
+ }
+ else
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ }
+ return err;
+}
+
+void KeyValueStoreManagerImpl::ForceKeyMapSave()
+{
+ OnScheduledKeyMapSave(nullptr, nullptr);
+}
+
+void KeyValueStoreManagerImpl::OnScheduledKeyMapSave(System::Layer * systemLayer, void * appState)
+{
+ SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_KvsStringKeyMap,
+ reinterpret_cast<const uint8_t *>(mKvsStoredKeyString), sizeof(mKvsStoredKeyString));
+}
+
+void KeyValueStoreManagerImpl::ScheduleKeyMapSave(void)
+{
+ /*
+ During commissioning, the key map will be modified multiples times subsequently.
+ Commit the key map in nvm once it as stabilized.
+ */
+ SystemLayer().StartTimer(
+ std::chrono::duration_cast<System::Clock::Timeout>(System::Clock::Seconds32(SILABS_KVS_SAVE_DELAY_SECONDS)),
+ KeyValueStoreManagerImpl::OnScheduledKeyMapSave, NULL);
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
+ size_t offset_bytes) const
+{
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint32_t nvm3Key;
+ CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key);
+ VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+ size_t outLen;
+ err = SILABSConfig::ReadConfigValueBin(nvm3Key, reinterpret_cast<uint8_t *>(value), value_size, outLen, offset_bytes);
+ if (read_bytes_size)
+ {
+ *read_bytes_size = outLen;
+ }
+
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ }
+
+ return err;
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
+{
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint32_t nvm3Key;
+ CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key, /* isSlotNeeded */ true);
+ VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+ err = SILABSConfig::WriteConfigValueBin(nvm3Key, reinterpret_cast<const uint8_t *>(value), value_size);
+ if (err == CHIP_NO_ERROR)
+ {
+ uint32_t keyIndex = nvm3Key - SILABSConfig::kConfigKey_KvsFirstKeySlot;
+ Platform::CopyString(mKvsStoredKeyString[keyIndex], key);
+ ScheduleKeyMapSave();
+ }
+
+ return err;
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
+{
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint32_t nvm3Key;
+ CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key);
+ VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+ err = SILABSConfig::ClearConfigValue(nvm3Key);
+ if (err == CHIP_NO_ERROR)
+ {
+ uint32_t keyIndex = CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key);
+ memset(mKvsStoredKeyString[keyIndex], 0, sizeof(mKvsStoredKeyString[keyIndex]));
+ ScheduleKeyMapSave();
+ }
+
+ return err;
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::ErasePartition(void)
+{
+ // Iterate over all the Matter Kvs nvm3 records and delete each one...
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ for (uint32_t nvm3Key = SILABSConfig::kMinConfigKey_MatterKvs; nvm3Key < SILABSConfig::kMaxConfigKey_MatterKvs; nvm3Key++)
+ {
+ err = SILABSConfig::ClearConfigValue(nvm3Key);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ break;
+ }
+ }
+
+ memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString));
+ return err;
+}
+
+} // namespace PersistedStorage
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp
new file mode 100644
index 0000000..f07fd94
--- /dev/null
+++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp
@@ -0,0 +1,335 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OTAImageProcessorImpl.h"
+#include <app/clusters/ota-requestor/OTADownloader.h>
+#include <app/clusters/ota-requestor/OTARequestorInterface.h>
+
+extern "C" {
+#include "btl_interface.h"
+#include "em_bus.h" // For CORE_CRITICAL_SECTION
+}
+
+#include <platform/silabs/SilabsConfig.h>
+
+/// No error, operation OK
+#define SL_BOOTLOADER_OK 0L
+
+namespace chip {
+
+// Define static memebers
+uint8_t OTAImageProcessorImpl::mSlotId = 0;
+uint32_t OTAImageProcessorImpl::mWriteOffset = 0;
+uint16_t OTAImageProcessorImpl::writeBufOffset = 0;
+uint8_t OTAImageProcessorImpl::writeBuffer[kAlignmentBytes] __attribute__((aligned(4))) = { 0 };
+
+CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
+{
+ DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast<intptr_t>(this));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::Finalize()
+{
+ DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast<intptr_t>(this));
+ return CHIP_NO_ERROR;
+}
+CHIP_ERROR OTAImageProcessorImpl::Apply()
+{
+ DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast<intptr_t>(this));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::Abort()
+{
+ DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast<intptr_t>(this));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
+{
+ if ((block.data() == nullptr) || block.empty())
+ {
+ return CHIP_ERROR_INVALID_ARGUMENT;
+ }
+
+ // Store block data for HandleProcessBlock to access
+ CHIP_ERROR err = SetBlock(block);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format());
+ }
+
+ DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast<intptr_t>(this));
+ return CHIP_NO_ERROR;
+}
+
+bool OTAImageProcessorImpl::IsFirstImageRun()
+{
+ OTARequestorInterface * requestor = chip::GetRequestorInstance();
+ if (requestor == nullptr)
+ {
+ return false;
+ }
+
+ return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage()
+{
+ OTARequestorInterface * requestor = chip::GetRequestorInstance();
+ if (requestor == nullptr)
+ {
+ return CHIP_ERROR_INTERNAL;
+ }
+
+ uint32_t currentVersion;
+ uint32_t targetVersion = requestor->GetTargetVersion();
+ ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion));
+ if (currentVersion != targetVersion)
+ {
+ ChipLogError(SoftwareUpdate, "Current software version = %" PRIu32 ", expected software version = %" PRIu32, currentVersion,
+ targetVersion);
+ return CHIP_ERROR_INCORRECT_STATE;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
+{
+ int32_t err = SL_BOOTLOADER_OK;
+ auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+
+ if (imageProcessor == nullptr)
+ {
+ ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
+ return;
+ }
+ else if (imageProcessor->mDownloader == nullptr)
+ {
+ ChipLogError(SoftwareUpdate, "mDownloader is null");
+ return;
+ }
+
+ ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload");
+
+ CORE_CRITICAL_SECTION(bootloader_init();)
+ mSlotId = 0; // Single slot until we support multiple images
+ writeBufOffset = 0;
+ mWriteOffset = 0;
+ imageProcessor->mParams.downloadedBytes = 0;
+
+ imageProcessor->mHeaderParser.Init();
+
+ // Not calling bootloader_eraseStorageSlot(mSlotId) here because we erase during each write
+
+ imageProcessor->mDownloader->OnPreparedForDownload(err == SL_BOOTLOADER_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL);
+}
+
+void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
+{
+ uint32_t err = SL_BOOTLOADER_OK;
+ auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+ if (imageProcessor == nullptr)
+ {
+ return;
+ }
+
+ // Pad the remainder of the write buffer with zeros and write it to bootloader storage
+ if (writeBufOffset != 0)
+ {
+ // Account for last bytes of the image not yet written to storage
+ imageProcessor->mParams.downloadedBytes += writeBufOffset;
+
+ while (writeBufOffset != kAlignmentBytes)
+ {
+ writeBuffer[writeBufOffset] = 0;
+ writeBufOffset++;
+ }
+
+ CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);)
+ if (err)
+ {
+ ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize bootloader_eraseWriteStorage() error %ld", err);
+ imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
+ return;
+ }
+ }
+
+ imageProcessor->ReleaseBlock();
+
+ ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully");
+}
+
+void OTAImageProcessorImpl::HandleApply(intptr_t context)
+{
+ uint32_t err = SL_BOOTLOADER_OK;
+
+ ChipLogProgress(SoftwareUpdate, "OTAImageProcessorImpl::HandleApply()");
+
+ // Force KVS to store pending keys such as data from StoreCurrentUpdateInfo()
+ chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().ForceKeyMapSave();
+
+ CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId, NULL);)
+ if (err != SL_BOOTLOADER_OK)
+ {
+ ChipLogError(SoftwareUpdate, "ERROR: bootloader_verifyImage() error %ld", err);
+
+ return;
+ }
+
+ CORE_CRITICAL_SECTION(err = bootloader_setImageToBootload(mSlotId);)
+ if (err != SL_BOOTLOADER_OK)
+ {
+ ChipLogError(SoftwareUpdate, "ERROR: bootloader_setImageToBootload() error %ld", err);
+
+ return;
+ }
+
+ // This reboots the device
+ CORE_CRITICAL_SECTION(bootloader_rebootAndInstall();)
+}
+
+void OTAImageProcessorImpl::HandleAbort(intptr_t context)
+{
+ auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+ if (imageProcessor == nullptr)
+ {
+ return;
+ }
+
+ // Not clearing the image storage area as it is done during each write
+ imageProcessor->ReleaseBlock();
+}
+
+void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
+{
+ uint32_t err = SL_BOOTLOADER_OK;
+ auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+ if (imageProcessor == nullptr)
+ {
+ ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
+ return;
+ }
+ else if (imageProcessor->mDownloader == nullptr)
+ {
+ ChipLogError(SoftwareUpdate, "mDownloader is null");
+ return;
+ }
+
+ ByteSpan block = imageProcessor->mBlock;
+ CHIP_ERROR chip_error = imageProcessor->ProcessHeader(block);
+
+ if (chip_error != CHIP_NO_ERROR)
+ {
+ ChipLogError(SoftwareUpdate, "Matter image header parser error %s", chip::ErrorStr(chip_error));
+ imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INVALID_FILE_IDENTIFIER);
+ return;
+ }
+
+ // Copy data into the word-aligned writeBuffer, once it fills write its contents to the bootloader storage
+ // Final data block is handled in HandleFinalize().
+ uint32_t blockReadOffset = 0;
+ while (blockReadOffset < block.size())
+ {
+ writeBuffer[writeBufOffset] = *((block.data()) + blockReadOffset);
+ writeBufOffset++;
+ blockReadOffset++;
+ if (writeBufOffset == kAlignmentBytes)
+ {
+ writeBufOffset = 0;
+
+ CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);)
+ if (err)
+ {
+ ChipLogError(SoftwareUpdate, "ERROR: In HandleProcessBlock bootloader_eraseWriteStorage() error %ld", err);
+ imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
+ return;
+ }
+ mWriteOffset += kAlignmentBytes;
+ imageProcessor->mParams.downloadedBytes += kAlignmentBytes;
+ }
+ }
+
+ imageProcessor->mDownloader->FetchNextData();
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block)
+{
+ if (mHeaderParser.IsInitialized())
+ {
+ OTAImageHeader header;
+ CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header);
+
+ // Needs more data to decode the header
+ ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR);
+ ReturnErrorOnFailure(error);
+
+ // SL TODO -- store version somewhere
+ ChipLogProgress(SoftwareUpdate, "Image Header software version: %ld payload size: %lu", header.mSoftwareVersion,
+ (long unsigned int) header.mPayloadSize);
+ mParams.totalFileBytes = header.mPayloadSize;
+ mHeaderParser.Clear();
+ }
+ return CHIP_NO_ERROR;
+}
+
+// Store block data for HandleProcessBlock to access
+CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block)
+{
+ if ((block.data() == nullptr) || block.empty())
+ {
+ return CHIP_NO_ERROR;
+ }
+
+ // Allocate memory for block data if we don't have enough already
+ if (mBlock.size() < block.size())
+ {
+ ReleaseBlock();
+
+ mBlock = MutableByteSpan(static_cast<uint8_t *>(chip::Platform::MemoryAlloc(block.size())), block.size());
+ if (mBlock.data() == nullptr)
+ {
+ return CHIP_ERROR_NO_MEMORY;
+ }
+ }
+
+ // Store the actual block data
+ CHIP_ERROR err = CopySpanToMutableSpan(block, mBlock);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(SoftwareUpdate, "Cannot copy block data: %" CHIP_ERROR_FORMAT, err.Format());
+ return err;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock()
+{
+ if (mBlock.data() != nullptr)
+ {
+ chip::Platform::MemoryFree(mBlock.data());
+ }
+
+ mBlock = MutableByteSpan();
+ return CHIP_NO_ERROR;
+}
+
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.h b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.h
new file mode 100644
index 0000000..30709bd
--- /dev/null
+++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.h
@@ -0,0 +1,80 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <app/clusters/ota-requestor/OTADownloader.h>
+#include <lib/core/OTAImageHeader.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/OTAImageProcessor.h>
+
+#include <fstream>
+
+namespace chip {
+
+class OTAImageProcessorImpl : public OTAImageProcessorInterface
+{
+public:
+ //////////// OTAImageProcessorInterface Implementation ///////////////
+ CHIP_ERROR PrepareDownload() override;
+ CHIP_ERROR Finalize() override;
+ CHIP_ERROR Apply() override;
+ CHIP_ERROR Abort() override;
+ CHIP_ERROR ProcessBlock(ByteSpan & block) override;
+ bool IsFirstImageRun() override;
+ CHIP_ERROR ConfirmCurrentImage() override;
+
+ void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
+ void SetOTAImageFile(const char * imageFile) { mImageFile = imageFile; }
+
+private:
+ //////////// Actual handlers for the OTAImageProcessorInterface ///////////////
+ static void HandlePrepareDownload(intptr_t context);
+ static void HandleFinalize(intptr_t context);
+ static void HandleApply(intptr_t context);
+ static void HandleAbort(intptr_t context);
+ static void HandleProcessBlock(intptr_t context);
+ CHIP_ERROR ProcessHeader(ByteSpan & block);
+
+ /**
+ * Called to allocate memory for mBlock if necessary and set it to block
+ */
+ CHIP_ERROR SetBlock(ByteSpan & block);
+
+ /**
+ * Called to release allocated memory for mBlock
+ */
+ CHIP_ERROR ReleaseBlock();
+
+ // EFR32 platform creates a single instance of OTAImageProcessorImpl class.
+ // If that changes then the use of static members and functions must be revisited
+ static uint32_t mWriteOffset; // End of last written block
+ static uint8_t mSlotId; // Bootloader storage slot
+ MutableByteSpan mBlock;
+ OTADownloader * mDownloader;
+ OTAImageHeaderParser mHeaderParser;
+ const char * mImageFile = nullptr;
+ static constexpr size_t kAlignmentBytes = 64;
+ // Intermediate, word-aligned buffer for writing to the bootloader storage.
+ // Bootloader storage API requires the buffer size to be a multiple of 4.
+ static uint8_t writeBuffer[kAlignmentBytes] __attribute__((aligned(4)));
+ // Offset indicates how far the write buffer has been filled
+ static uint16_t writeBufOffset;
+};
+
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/PlatformManagerImpl.cpp b/src/platform/silabs/SiWx917/PlatformManagerImpl.cpp
new file mode 100644
index 0000000..25de6d5
--- /dev/null
+++ b/src/platform/silabs/SiWx917/PlatformManagerImpl.cpp
@@ -0,0 +1,163 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Nest Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides an implementation of the PlatformManager object
+ * for Silabs platforms using the Silicon Labs SDK.
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/FreeRTOS/SystemTimeSupport.h>
+#include <platform/KeyValueStoreManager.h>
+#include <platform/PlatformManager.h>
+#include <platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp>
+#include <platform/silabs/DiagnosticDataProviderImpl.h>
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#include <lwip/tcpip.h>
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+#include "AppConfig.h"
+#include "FreeRTOS.h"
+
+namespace chip {
+namespace DeviceLayer {
+
+PlatformManagerImpl PlatformManagerImpl::sInstance;
+
+CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
+{
+ CHIP_ERROR err;
+
+ // Initialize the configuration system.
+ err = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init();
+ SuccessOrExit(err);
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+ // Initialize LwIP.
+ tcpip_init(NULL, NULL);
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+ ReturnErrorOnFailure(System::Clock::InitClock_RealTime());
+
+ // Call _InitChipStack() on the generic implementation base class
+ // to finish the initialization process.
+ err = Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::_InitChipStack();
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+void PlatformManagerImpl::_Shutdown()
+{
+ uint64_t upTime = 0;
+
+ if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR)
+ {
+ uint32_t totalOperationalHours = 0;
+
+ if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR)
+ {
+ ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast<uint32_t>(upTime / 3600));
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node");
+ }
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot");
+ }
+
+ Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::_Shutdown();
+}
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+void PlatformManagerImpl::HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData)
+{
+ ChipDeviceEvent event;
+ memset(&event, 0, sizeof(event));
+ event.Type = DeviceEventType::kWFXSystemEvent;
+ event.Platform.WFXSystemEvent.eventBase = eventBase;
+
+ if (eventBase == WIFI_EVENT)
+ {
+ switch (eventData->header.id)
+ {
+ case SL_WFX_STARTUP_IND_ID:
+ memcpy(&event.Platform.WFXSystemEvent.data.startupEvent, eventData,
+ sizeof(event.Platform.WFXSystemEvent.data.startupEvent));
+ break;
+ case SL_WFX_CONNECT_IND_ID:
+ memcpy(&event.Platform.WFXSystemEvent.data.connectEvent, eventData,
+ sizeof(event.Platform.WFXSystemEvent.data.connectEvent));
+ break;
+ case SL_WFX_DISCONNECT_IND_ID:
+ memcpy(&event.Platform.WFXSystemEvent.data.disconnectEvent, eventData,
+ sizeof(event.Platform.WFXSystemEvent.data.disconnectEvent));
+ break;
+ // case SL_WFX_RECEIVED_IND_ID:
+ // memcpy(&event.Platform.WFXSystemEvent.data.receivedEvent, eventData,
+ // sizeof(event.Platform.WFXSystemEvent.data.receivedEvent));
+ // break;
+ // case SL_WFX_GENERIC_IND_ID:
+ // memcpy(&event.Platform.WFXSystemEvent.data.genericEvent, eventData,
+ // sizeof(event.Platform.WFXSystemEvent.data.genericEvent));
+ // break;
+ // case SL_WFX_EXCEPTION_IND_ID:
+ // memcpy(&event.Platform.WFXSystemEvent.data.exceptionEvent, eventData,
+ // sizeof(event.Platform.WFXSystemEvent.data.exceptionEvent));
+ // break;
+ // case SL_WFX_ERROR_IND_ID:
+ // memcpy(&event.Platform.WFXSystemEvent.data.errorEvent, eventData,
+ // sizeof(event.Platform.WFXSystemEvent.data.errorEvent));
+ // break;
+ default:
+ break;
+ }
+ }
+ else if (eventBase == IP_EVENT)
+ {
+ switch (eventData->header.id)
+ {
+ case IP_EVENT_STA_GOT_IP:
+ memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData,
+ sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent));
+ break;
+ case IP_EVENT_GOT_IP6:
+ memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData,
+ sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent));
+ break;
+ case IP_EVENT_STA_LOST_IP:
+ memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData,
+ sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent));
+ break;
+ default:
+ break;
+ }
+ }
+
+ (void) sInstance.PostEvent(&event);
+}
+#endif
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/ThreadStackManagerImpl.cpp b/src/platform/silabs/SiWx917/ThreadStackManagerImpl.cpp
new file mode 100644
index 0000000..16d7922
--- /dev/null
+++ b/src/platform/silabs/SiWx917/ThreadStackManagerImpl.cpp
@@ -0,0 +1,173 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Nest Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides an implementation of the ThreadStackManager object for
+ * EFR32 platforms using the Silicon Labs SDK and the OpenThread
+ * stack.
+ *
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.cpp>
+#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp>
+#include <platform/OpenThread/OpenThreadUtils.h>
+#include <platform/ThreadStackManager.h>
+
+#include <openthread/platform/entropy.h>
+
+#include <lib/support/CHIPPlatformMemory.h>
+
+namespace chip {
+namespace DeviceLayer {
+
+using namespace ::chip::DeviceLayer::Internal;
+
+ThreadStackManagerImpl ThreadStackManagerImpl::sInstance;
+
+CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack(void)
+{
+ return InitThreadStack(NULL);
+}
+
+CHIP_ERROR ThreadStackManagerImpl::InitThreadStack(otInstance * otInst)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ // Initialize the generic implementation base classes.
+ err = GenericThreadStackManagerImpl_FreeRTOS<ThreadStackManagerImpl>::DoInit();
+ SuccessOrExit(err);
+ err = GenericThreadStackManagerImpl_OpenThread<ThreadStackManagerImpl>::DoInit(otInst);
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+bool ThreadStackManagerImpl::IsInitialized()
+{
+ return sInstance.mThreadStackLock != NULL;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
+
+using namespace ::chip::DeviceLayer;
+
+/**
+ * Glue function called directly by the OpenThread stack when tasklet processing work
+ * is pending.
+ */
+extern "C" void otTaskletsSignalPending(otInstance * p_instance)
+{
+ ThreadStackMgrImpl().SignalThreadActivityPending();
+}
+
+/**
+ * Glue function called directly by the OpenThread stack when system event processing work
+ * is pending.
+ */
+extern "C" void otSysEventSignalPending(void)
+{
+ BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR();
+ portYIELD_FROM_ISR(yieldRequired);
+}
+
+extern "C" void * otPlatCAlloc(size_t aNum, size_t aSize)
+{
+ return CHIPPlatformMemoryCalloc(aNum, aSize);
+}
+
+extern "C" void otPlatFree(void * aPtr)
+{
+ CHIPPlatformMemoryFree(aPtr);
+}
+
+extern "C" __WEAK void sl_openthread_init(void)
+{
+ // Place holder for enabling Silabs specific features available only through Simplicity Studio
+}
+
+/**
+ * @brief Openthread UART implementation for the CLI is conflicting
+ * with the UART implemented for Pigweed RPC as they use the same UART port
+ *
+ * We now only build the uart as implemented in
+ * connectedhomeip/examples/platform/efr32/uart.c
+ * and remap OT functions to use our uart api.
+ *
+ * For now OT CLI isn't usable when the examples are built with pw_rpc
+ */
+
+#ifndef PW_RPC_ENABLED
+#include "uart.h"
+#endif
+
+extern "C" otError otPlatUartEnable(void)
+{
+#ifdef PW_RPC_ENABLED
+ return OT_ERROR_NOT_IMPLEMENTED;
+#else
+ uartConsoleInit();
+ return OT_ERROR_NONE;
+#endif
+}
+
+#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
+
+extern "C" otError otPlatUartSend(const uint8_t * aBuf, uint16_t aBufLength)
+{
+#ifdef PW_RPC_ENABLED
+ return OT_ERROR_NOT_IMPLEMENTED;
+#else
+ if (uartConsoleWrite((const char *) aBuf, aBufLength) > 0)
+ {
+ otPlatUartSendDone();
+ return OT_ERROR_NONE;
+ }
+ return OT_ERROR_FAILED;
+#endif
+}
+
+extern "C" void efr32UartProcess(void)
+{
+#if !defined(PW_RPC_ENABLED) && !defined(ENABLE_CHIP_SHELL)
+ uint8_t tempBuf[128] = { 0 };
+ // will read the data available up to 128bytes
+ uint16_t count = uartConsoleRead((char *) tempBuf, 128);
+ if (count > 0)
+ {
+ // ot process Received data for CLI cmds
+ otPlatUartReceived(tempBuf, count);
+ }
+#endif
+}
+
+extern "C" __WEAK otError otPlatUartFlush(void)
+{
+ return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+extern "C" __WEAK otError otPlatUartDisable(void)
+{
+ return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+#endif // CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
diff --git a/src/platform/silabs/SiWx917/args.gni b/src/platform/silabs/SiWx917/args.gni
new file mode 100644
index 0000000..6e7ac8d
--- /dev/null
+++ b/src/platform/silabs/SiWx917/args.gni
@@ -0,0 +1,61 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+
+# ARM architecture flags will be set based on silabs_family.
+arm_platform_config = "${efr32_sdk_build_root}/efr32_arm.gni"
+
+mbedtls_target = "${efr32_sdk_build_root}:efr32_sdk"
+
+openthread_external_mbedtls = mbedtls_target
+
+# default to platform crypto implementation but allow commandline override
+if (chip_crypto == "") {
+ chip_crypto = "platform"
+}
+
+chip_device_platform = "efr32"
+
+#Net work configuration OpenThread
+lwip_platform = "efr32"
+chip_mdns = "platform"
+chip_inet_config_enable_ipv4 = false
+chip_inet_config_enable_tcp_endpoint = false
+chip_system_config_use_open_thread_inet_endpoints = true
+chip_with_lwip = false
+
+chip_build_tests = false
+
+# Transitional CommissionableDataProvider not used anymore
+# examples/platform/silabs/efr32/EFR32DeviceDataProvider is now used.
+chip_use_transitional_commissionable_data_provider = false
+
+openthread_root = "${chip_root}/third_party/openthread/ot-efr32/openthread"
+openthread_core_config_platform_check_file =
+ "openthread-core-efr32-config-check.h"
+openthread_project_core_config_file = "OpenThreadConfig.h"
+openthread_core_config_deps = [ "${chip_root}/examples/platform/silabs/efr32:openthread_core_config_efr32_chip_examples" ]
+
+chip_config_memory_management = "platform"
+
+pw_build_LINK_DEPS = [
+ "$dir_pw_assert:impl",
+ "$dir_pw_log:impl",
+]
diff --git a/src/platform/silabs/SiWx917/efr32-chip-mbedtls-config.h b/src/platform/silabs/SiWx917/efr32-chip-mbedtls-config.h
new file mode 100644
index 0000000..049c12c
--- /dev/null
+++ b/src/platform/silabs/SiWx917/efr32-chip-mbedtls-config.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "em_device.h"
+#include "em_se.h"
+
+#if CHIP_HAVE_CONFIG_H
+#include <crypto/CryptoBuildConfig.h>
+#endif // CHIP_HAVE_CONFIG_H
+
+/**
+ * Enable H Crypto and Entropy modules
+ */
+#define MBEDTLS_AES_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_SHA224_C
+#define MBEDTLS_SHA256_C
+
+#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
+
+#define MBEDTLS_AES_ROM_TABLES
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CMAC_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ECDH_LEGACY_CONTEXT
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECJPAKE_C
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_NIST_OPTIM
+#define MBEDTLS_ENTROPY_FORCE_SHA256
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+#define MBEDTLS_HAVE_ASM
+#define MBEDTLS_HKDF_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_MD_C
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_OID_C
+#define MBEDTLS_PEM_PARSE_C
+#define MBEDTLS_PEM_WRITE_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#if CHIP_CRYPTO_MBEDTLS
+#define MBEDTLS_PKCS5_C
+#endif
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+#define MBEDTLS_PSA_CRYPTO_DRIVERS
+#define MBEDTLS_PSA_CRYPTO_STORAGE_C
+#define MBEDTLS_SHA256_SMALLER
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_COOKIE_C
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#define MBEDTLS_SSL_EXPORT_KEYS
+#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_PROTO_DTLS
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+
+#if CHIP_CRYPTO_PLATFORM
+#define MBEDTLS_USE_PSA_CRYPTO
+#endif
+
+#define MBEDTLS_X509_CREATE_C
+#define MBEDTLS_X509_CSR_WRITE_C
+#define MBEDTLS_X509_CRL_PARSE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+#define MBEDTLS_X509_CSR_PARSE_C
+#define MBEDTLS_X509_USE_C
+
+#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */
+#define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */
+#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */
+#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */
+#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */
+#define MBEDTLS_ENTROPY_MAX_SOURCES 2 /**< Maximum number of sources supported */
+
+#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 900 /**< Maxium fragment length in bytes */
+#else
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 /**< Maxium fragment length in bytes */
+#endif
+
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
+
+#define MBEDTLS_CIPHER_MODE_WITH_PADDING
+
+#include "check_crypto_config.h"
+#include "config-device-acceleration.h"
+#include "mbedtls/check_config.h"
+#include "mbedtls/config_psa.h"
diff --git a/src/platform/silabs/SiWx917/efr32-mbedtls-psa-crypto-config.h b/src/platform/silabs/SiWx917/efr32-mbedtls-psa-crypto-config.h
new file mode 100644
index 0000000..6df9724
--- /dev/null
+++ b/src/platform/silabs/SiWx917/efr32-mbedtls-psa-crypto-config.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright (c) 2020-2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// ADD USER PSA CRYPTO CONFIG HERE
+#define SL_PSA_KEY_USER_SLOT_COUNT (4)
+
+#define SL_PSA_ITS_USER_MAX_FILES (128)
+
+#include "em_device.h"
+#if defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
+// Use accelerated HMAC when we have it
+#define MBEDTLS_PSA_ACCEL_ALG_HMAC
+// Use accelerated ECDSA/ECDH when we have it
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256
+#define MBEDTLS_PSA_ACCEL_ALG_ECDH
+#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#else
+// Devices without SEMAILBOX or CRYPTOACC don't have HMAC top-level accelerated
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
+// Devices without SEMAILBOX or CRYPTOACC don't have fully implemented ECDSA/ECDH
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
+#endif
+// end of user configuration section >>>
+
+// AUTO GENERATED PSA CONFIG SECTION BELOW. **KEEP AS IS FUTURE GSDK UPDATE**
+#define PSA_WANT_KEY_TYPE_AES
+#define PSA_WANT_ALG_CMAC
+#define PSA_WANT_ALG_SHA_256
+#define PSA_WANT_ALG_CCM
+#define PSA_WANT_ALG_ECB_NO_PADDING
+#define PSA_WANT_ALG_ECDSA
+#define PSA_WANT_ALG_ECDH
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+#define PSA_WANT_ECC_SECP_R1_256
+#define PSA_WANT_ALG_HKDF
+#define PSA_WANT_ALG_HMAC
+#define PSA_WANT_KEY_TYPE_HMAC
+#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_1
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_224
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
+#define MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
+#define MBEDTLS_PSA_ACCEL_ALG_CTR
+#define MBEDTLS_PSA_ACCEL_ALG_CFB
+#define MBEDTLS_PSA_ACCEL_ALG_OFB
+#define MBEDTLS_PSA_ACCEL_ALG_GCM
+#define MBEDTLS_PSA_ACCEL_ALG_CCM
+#define MBEDTLS_PSA_ACCEL_ALG_CMAC
+
+#define MBEDTLS_PSA_KEY_SLOT_COUNT (15 + 1 + SL_PSA_KEY_USER_SLOT_COUNT)
+#define SL_PSA_ITS_MAX_FILES (1 + SL_PSA_ITS_USER_MAX_FILES)
diff --git a/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp b/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp
new file mode 100644
index 0000000..15c6785
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp
@@ -0,0 +1,149 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if LWIP_IPV4 && LWIP_DHCP
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#include "dhcp_client.h"
+#include "lwip/dhcp.h"
+#include "wfx_host_events.h"
+#include "wifi_config.h"
+
+#include "AppConfig.h"
+#include "FreeRTOS.h"
+#include "event_groups.h"
+
+#define MAX_DHCP_TRIES 4
+#define NETIF_IPV4_ADDRESS(X, Y) (((X) >> (8 * Y)) & 0xFF)
+
+/* Station IP address */
+uint8_t sta_ip_addr0 = STA_IP_ADDR0_DEFAULT;
+uint8_t sta_ip_addr1 = STA_IP_ADDR1_DEFAULT;
+uint8_t sta_ip_addr2 = STA_IP_ADDR2_DEFAULT;
+uint8_t sta_ip_addr3 = STA_IP_ADDR3_DEFAULT;
+uint8_t sta_netmask_addr0 = STA_NETMASK_ADDR0_DEFAULT;
+uint8_t sta_netmask_addr1 = STA_NETMASK_ADDR1_DEFAULT;
+uint8_t sta_netmask_addr2 = STA_NETMASK_ADDR2_DEFAULT;
+uint8_t sta_netmask_addr3 = STA_NETMASK_ADDR3_DEFAULT;
+uint8_t sta_gw_addr0 = STA_GW_ADDR0_DEFAULT;
+uint8_t sta_gw_addr1 = STA_GW_ADDR1_DEFAULT;
+uint8_t sta_gw_addr2 = STA_GW_ADDR2_DEFAULT;
+uint8_t sta_gw_addr3 = STA_GW_ADDR3_DEFAULT;
+
+/// Current DHCP state machine state.
+static volatile uint8_t dhcp_state = DHCP_OFF;
+
+/*****************************************************************************
+ * @fn void dhcpclient_set_link_state(int link_up)
+ * @brief
+ * Notify DHCP client task about the wifi status
+ * @param link_up link status
+ * @return None
+ ******************************************************************************/
+void dhcpclient_set_link_state(int link_up)
+{
+ if (link_up)
+ {
+ dhcp_state = DHCP_START;
+ SILABS_LOG("DHCP: Starting");
+ }
+ else
+ {
+ /* Update DHCP state machine */
+ dhcp_state = DHCP_LINK_DOWN;
+ }
+}
+
+/**********************************************************************************
+ * @fn uint8_t dhcpclient_poll(void *arg)
+ * @brief
+ * Don't need a task here. We get polled every 250ms
+ * @return None
+ ************************************************************************************/
+uint8_t dhcpclient_poll(void * arg)
+{
+ struct netif * netif = (struct netif *) arg;
+ ip_addr_t ipaddr;
+ ip_addr_t netmask;
+ ip_addr_t gw;
+ struct dhcp * dhcp;
+
+ switch (dhcp_state)
+ {
+ case DHCP_START:
+ SILABS_LOG("DHCP: Wait addr");
+ ip_addr_set_zero_ip4(&netif->ip_addr);
+ ip_addr_set_zero_ip4(&netif->netmask);
+ ip_addr_set_zero_ip4(&netif->gw);
+ dhcp_start(netif);
+ dhcp_state = DHCP_WAIT_ADDRESS;
+ break;
+
+ case DHCP_WAIT_ADDRESS:
+ if (dhcp_supplied_address(netif))
+ {
+ dhcp_state = DHCP_ADDRESS_ASSIGNED;
+
+ uint64_t addr = netif->ip_addr.u_addr.ip4.addr;
+ SILABS_LOG("DHCP IP: %d.%d.%d.%d", NETIF_IPV4_ADDRESS(addr, 0), NETIF_IPV4_ADDRESS(addr, 1),
+ NETIF_IPV4_ADDRESS(addr, 2), NETIF_IPV4_ADDRESS(addr, 3));
+ }
+ else
+ {
+ dhcp = (struct dhcp *) netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
+
+ /* DHCP timeout */
+ if (dhcp->tries > MAX_DHCP_TRIES)
+ {
+ dhcp_state = DHCP_TIMEOUT;
+
+ SILABS_LOG("*ERR*DHCP: Failed");
+ /* Stop DHCP */
+ dhcp_stop(netif);
+
+ /* TODO - I am not sure that this is best */
+ /* Static address used */
+ IP_ADDR4(&ipaddr, sta_ip_addr0, sta_ip_addr1, sta_ip_addr2, sta_ip_addr3);
+ IP_ADDR4(&netmask, sta_netmask_addr0, sta_netmask_addr1, sta_netmask_addr2, sta_netmask_addr3);
+ IP_ADDR4(&gw, sta_gw_addr0, sta_gw_addr1, sta_gw_addr2, sta_gw_addr3);
+ netif_set_addr(netif, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gw));
+ }
+ }
+ break;
+
+ case DHCP_LINK_DOWN:
+ /* Stop DHCP */
+ SILABS_LOG("*ERR*DHCP Link down");
+ dhcp_stop(netif);
+ dhcp_state = DHCP_OFF;
+ break;
+ default:
+ break;
+ }
+ return dhcp_state;
+}
+
+#endif /* LWIP_IPV4 && LWIP_DHCP */
diff --git a/src/platform/silabs/SiWx917/wifi/dhcp_client.h b/src/platform/silabs/SiWx917/wifi/dhcp_client.h
new file mode 100644
index 0000000..3040f71
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/dhcp_client.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if LWIP_IPV4 && LWIP_DHCP
+
+#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// DHCP client states
+#define DHCP_OFF (uint8_t) 0
+#define DHCP_START (uint8_t) 1
+#define DHCP_WAIT_ADDRESS (uint8_t) 2
+#define DHCP_ADDRESS_ASSIGNED (uint8_t) 3
+#define DHCP_TIMEOUT (uint8_t) 4
+#define DHCP_LINK_DOWN (uint8_t) 5
+
+/*****************************************************************************
+ * @fn void dhcpclient_set_link_state(int link_up)
+ * @brief
+ * Notify DHCP client task about the wifi status
+ * @param link_up link status
+ ******************************************************************************/
+void dhcpclient_set_link_state(int link_up);
+uint8_t dhcpclient_poll(void * arg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIP_IPV4 && LWIP_DHCP */
diff --git a/src/platform/silabs/SiWx917/wifi/ethernetif.cpp b/src/platform/silabs/SiWx917/wifi/ethernetif.cpp
new file mode 100644
index 0000000..d1fcc01
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/ethernetif.cpp
@@ -0,0 +1,461 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Includes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#ifndef WF200_WIFI
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+#endif
+
+#include "wfx_host_events.h"
+#include "wifi_config.h"
+#ifdef WF200_WIFI
+#include "sl_wfx.h"
+#endif
+/* LwIP includes. */
+#include "ethernetif.h"
+#include "lwip/ethip6.h"
+#include "lwip/timeouts.h"
+#include "netif/etharp.h"
+
+#ifndef SILABS_LOG
+extern "C" {
+void efr32Log(const char * aFormat, ...);
+#define SILABS_LOG(...) efr32Log(__VA_ARGS__);
+}
+#endif
+
+StaticSemaphore_t xEthernetIfSemaBuffer;
+
+/*****************************************************************************
+ * Defines
+ ******************************************************************************/
+#define STATION_NETIF0 's'
+#define STATION_NETIF1 't'
+
+#define LWIP_FRAME_ALIGNMENT 60
+
+uint32_t gOverrunCount = 0;
+
+/*****************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*****************************************************************************
+ * @fn static void low_level_init(struct netif *netif)
+ * @brief
+ * Initializes the hardware parameters. Called from ethernetif_init().
+ *
+ * @param[in] netif: the already initialized lwip network interface structure
+ *
+ * @return
+ * None
+ ******************************************************************************/
+static void low_level_init(struct netif * netif)
+{
+ /* set netif MAC hardware address length */
+ netif->hwaddr_len = ETH_HWADDR_LEN;
+
+ /* Set netif MAC hardware address */
+ sl_wfx_mac_address_t mac_addr;
+
+ wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac_addr);
+
+ netif->hwaddr[0] = mac_addr.octet[0];
+ netif->hwaddr[1] = mac_addr.octet[1];
+ netif->hwaddr[2] = mac_addr.octet[2];
+ netif->hwaddr[3] = mac_addr.octet[3];
+ netif->hwaddr[4] = mac_addr.octet[4];
+ netif->hwaddr[5] = mac_addr.octet[5];
+
+ /* Set netif maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* Accept broadcast address and ARP traffic */
+ netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
+
+#if LWIP_IPV6_MLD
+ netif->flags |= NETIF_FLAG_MLD6;
+#endif /* LWIP_IPV6_MLD */
+}
+
+/********************************************************************************
+ * @fn static void low_level_input(struct netif *netif, uint8_t *b, uint16_t len)
+ * @brief
+ * Make PBUF out of a linear buffer - that can be fed into lwip
+ * @param[in] netif: the already initialized lwip network interface structure
+ * @param[in] len: length
+ * @return
+ * None
+ ************************************************************************************/
+static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len)
+{
+ struct pbuf *p, *q;
+ uint32_t bufferoffset;
+
+ if (len <= 0)
+ {
+ return;
+ }
+ if (len < LWIP_FRAME_ALIGNMENT)
+ { /* 60 : LWIP frame alignment */
+ len = LWIP_FRAME_ALIGNMENT;
+ }
+
+ /* Drop packets originated from the same interface and is not destined for the said interface */
+ const uint8_t * src_mac = b + netif->hwaddr_len;
+ const uint8_t * dst_mac = b;
+
+ if (!(ip6_addr_ispreferred(netif_ip6_addr_state(netif, 0))) && (memcmp(netif->hwaddr, src_mac, netif->hwaddr_len) == 0) &&
+ (memcmp(netif->hwaddr, dst_mac, netif->hwaddr_len) != 0))
+ {
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("%s: DROP, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__,
+
+ dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5],
+
+ src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5],
+
+ b[12], b[13]);
+#endif
+ return;
+ }
+
+ /* We allocate a pbuf chain of pbufs from the Lwip buffer pool
+ * and copy the data to the pbuf chain
+ */
+ if ((p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL)) != STRUCT_PBUF)
+ {
+ for (q = p, bufferoffset = 0; q != NULL; q = q->next)
+ {
+ memcpy((uint8_t *) q->payload, (uint8_t *) b + bufferoffset, q->len);
+ bufferoffset += q->len;
+ }
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("%s: ACCEPT %d, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__,
+ bufferoffset,
+
+ dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5],
+
+ src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5],
+
+ b[12], b[13]);
+#endif
+
+ if (netif->input(p, netif) != ERR_OK)
+ {
+ gOverrunCount++;
+ SILABS_LOG("overrun count entering when fail to alloc value %d", gOverrunCount);
+ pbuf_free(p);
+ }
+ }
+ else
+ {
+ gOverrunCount++;
+ SILABS_LOG("overrun count entering when fail to alloc value %d", gOverrunCount);
+ }
+}
+
+/*****************************************************************************
+ * @fn static err_t low_level_output(struct netif *netif, struct pbuf *p)
+ * @brief
+ * This function should does the actual transmission of the packet(s).
+ * The packet is contained in the pbuf that is passed to the function.
+ * This pbuf might be chained.
+ *
+ * @param[in] netif: the lwip network interface structure
+ *
+ * @param[in] p: the packet to send
+ *
+ * @return
+ * ERR_OK if successful
+ ******************************************************************************/
+#ifdef WF200_WIFI
+static err_t low_level_output(struct netif * netif, struct pbuf * p)
+{
+ struct pbuf * q;
+ sl_wfx_send_frame_req_t * tx_buffer;
+ uint8_t * buffer;
+ uint32_t framelength, asize;
+ uint32_t bufferoffset;
+ uint32_t padding;
+ sl_status_t result;
+
+ for (q = p, framelength = 0; q != NULL; q = q->next)
+ {
+ framelength += q->len;
+ }
+ if (framelength < LWIP_FRAME_ALIGNMENT)
+ { /* 60 : Frame alignment for LWIP */
+ padding = LWIP_FRAME_ALIGNMENT - framelength;
+ }
+ else
+ {
+ padding = 0;
+ }
+
+ /* choose padding of 64 */
+ asize = SL_WFX_ROUND_UP(framelength + padding, 64) + sizeof(sl_wfx_send_frame_req_t);
+ // 12 is size of other data in buffer struct, user shouldn't have to care about this?
+ if (sl_wfx_host_allocate_buffer((void **) &tx_buffer, SL_WFX_TX_FRAME_BUFFER, asize) != SL_STATUS_OK)
+ {
+ SILABS_LOG("*ERR*EN-Out: No mem frame len=%d", framelength);
+ gOverrunCount++;
+ SILABS_LOG("overrun count exiting when faied to alloc value %d", gOverrunCount);
+ return ERR_MEM;
+ }
+ buffer = tx_buffer->body.packet_data;
+ /* copy frame from pbufs to driver buffers */
+ for (q = p, bufferoffset = 0; q != NULL; q = q->next)
+ {
+ /* Get bytes in current lwIP buffer */
+ memcpy((uint8_t *) ((uint8_t *) buffer + bufferoffset), (uint8_t *) ((uint8_t *) q->payload), q->len);
+ bufferoffset += q->len;
+ }
+ /* No requirement to do this - but we should for security */
+ if (padding)
+ {
+ memset(buffer + bufferoffset, 0, padding);
+ framelength += padding;
+ }
+ /* transmit */
+ int i = 0;
+ result = SL_STATUS_FAIL;
+
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("WF200: Out %d", (int) framelength);
+#endif
+
+ /* send the generated frame over Wifi network */
+ while ((result != SL_STATUS_OK) && (i++ < 10))
+ {
+ result = sl_wfx_send_ethernet_frame(tx_buffer, framelength, SL_WFX_STA_INTERFACE, PRIORITY_0);
+ }
+ sl_wfx_host_free_buffer(tx_buffer, SL_WFX_TX_FRAME_BUFFER);
+
+ if (result != SL_STATUS_OK)
+ {
+ SILABS_LOG("*ERR*Send enet %d", (int) framelength);
+ return ERR_IF;
+ }
+ return ERR_OK;
+}
+
+/*****************************************************************************
+ * @fn void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t *rx_buffer)
+ * @brief
+ * This function implements the wf200 received frame callback.
+ * Called from the context of the bus_task (not ISR)
+ *
+ * @param[in] rx_buffer: the ethernet frame received by the wf200
+ *
+ * @return
+ * None
+ ******************************************************************************/
+void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer)
+{
+ struct netif * netif;
+
+ /* Check packet interface to send to AP or STA interface */
+ if ((rx_buffer->header.info & SL_WFX_MSG_INFO_INTERFACE_MASK) == (SL_WFX_STA_INTERFACE << SL_WFX_MSG_INFO_INTERFACE_OFFSET))
+ {
+
+ /* Send received frame to station interface */
+ if ((netif = wfx_get_netif(SL_WFX_STA_INTERFACE)) != NULL)
+ {
+ uint8_t * buffer;
+ uint16_t len;
+
+ len = rx_buffer->body.frame_length;
+ buffer = (uint8_t *) &(rx_buffer->body.frame[rx_buffer->body.frame_padding]);
+
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("WF200: In %d", (int) len);
+#endif
+
+ low_level_input(netif, buffer, len);
+ }
+ else
+ {
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("WF200: NO-INTF");
+#endif
+ }
+ }
+ else
+ {
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("WF200: Invalid frame IN");
+#endif
+ }
+}
+
+#else /* For RS911x - using LWIP */
+static SemaphoreHandle_t ethout_sem;
+/*****************************************************************************
+ * @fn static err_t low_level_output(struct netif *netif, struct pbuf *p)
+ * @brief
+ * This function is called from LWIP task when LWIP stack
+ * has some data to be forwarded over WiFi Network
+ *
+ * @param[in] netif: lwip network interface
+ *
+ * @param[in] p: the packet to send
+ *
+ * @return
+ * ERR_OK if successful
+ ******************************************************************************/
+static err_t low_level_output(struct netif * netif, struct pbuf * p)
+{
+ void * rsipkt;
+ struct pbuf * q;
+ uint16_t framelength;
+
+ if (xSemaphoreTake(ethout_sem, portMAX_DELAY) != pdTRUE)
+ {
+ return ERR_IF;
+ }
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("EN-RSI: Output");
+#endif
+ if ((netif->flags & (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) != (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP))
+ {
+ SILABS_LOG("EN-RSI:NOT UP");
+ xSemaphoreGive(ethout_sem);
+ return ERR_IF;
+ }
+ /* Confirm if packet is allocated */
+ rsipkt = wfx_rsi_alloc_pkt();
+ if (!rsipkt)
+ {
+ SILABS_LOG("EN-RSI:No buf");
+ xSemaphoreGive(ethout_sem);
+ return ERR_IF;
+ }
+
+#ifdef WIFI_DEBUG_ENABLED
+ uint8_t * b = (uint8_t *) p->payload;
+ SILABS_LOG("EN-RSI: Out [%02x:%02x:%02x:%02x:%02x:%02x][%02x:%02x:%02x:%02x:%02x:%02x]type=%02x%02x", b[0], b[1], b[2], b[3],
+ b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]);
+#endif
+ /* Generate the packet */
+ for (q = p, framelength = 0; q != NULL; q = q->next)
+ {
+ wfx_rsi_pkt_add_data(rsipkt, (uint8_t *) (q->payload), (uint16_t) q->len, framelength);
+ framelength += q->len;
+ }
+ if (framelength < LWIP_FRAME_ALIGNMENT)
+ {
+ /* Add junk data to the end for frame alignment if framelength is less than 60 */
+ wfx_rsi_pkt_add_data(rsipkt, (uint8_t *) (p->payload), LWIP_FRAME_ALIGNMENT - framelength, framelength);
+ }
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("EN-RSI: Sending %d", framelength);
+#endif
+
+ /* forward the generated packet to RSI to
+ * send the data over wifi network
+ */
+ if (wfx_rsi_send_data(rsipkt, framelength))
+ {
+ SILABS_LOG("*ERR*EN-RSI:Send fail");
+ xSemaphoreGive(ethout_sem);
+ return ERR_IF;
+ }
+
+#ifdef WIFI_DEBUG_ENABLED
+ SILABS_LOG("EN-RSI:Xmit %d", framelength);
+#endif
+ xSemaphoreGive(ethout_sem);
+
+ return ERR_OK;
+}
+
+/*****************************************************************************
+ * @fn void wfx_host_received_sta_frame_cb(uint8_t *buf, int len)
+ * @brief
+ * host received frame cb
+ *
+ * @param[in] buf: buffer
+ *
+ * @param[in] len: length
+ *
+ * @return
+ * None
+ ******************************************************************************/
+void wfx_host_received_sta_frame_cb(uint8_t * buf, int len)
+{
+ struct netif * ifp;
+
+ /* get the network interface for STATION interface,
+ * and forward the received frame buffer to LWIP
+ */
+ if ((ifp = wfx_get_netif(SL_WFX_STA_INTERFACE)) != (struct netif *) 0)
+ {
+ low_level_input(ifp, buf, len);
+ }
+}
+
+#endif /* RS911x - with LWIP */
+
+/*****************************************************************************
+ * @fn err_t sta_ethernetif_init(struct netif *netif)
+ * @brief
+ * sta ethernet if initialization
+ *
+ * @param[in] netif: the lwip network interface structure
+ *
+ * @return
+ * ERR_OK if successful
+ ******************************************************************************/
+err_t sta_ethernetif_init(struct netif * netif)
+{
+ LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+ /* Set the netif name to identify the interface */
+ netif->name[0] = STATION_NETIF0;
+ netif->name[1] = STATION_NETIF1;
+
+#if LWIP_IPV4 && LWIP_ARP
+ netif->output = etharp_output;
+#endif /* #if LWIP_IPV4 && LWIP_ARP */
+#if LWIP_IPV6 && LWIP_ETHERNET
+ netif->output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 && LWIP_ETHERNET */
+ netif->linkoutput = low_level_output;
+
+ /* initialize the hardware */
+ low_level_init(netif);
+#ifndef WF200_WIFI
+ /* Need single output only */
+ ethout_sem = xSemaphoreCreateBinaryStatic(&xEthernetIfSemaBuffer);
+ xSemaphoreGive(ethout_sem);
+#endif
+ return ERR_OK;
+}
diff --git a/src/platform/silabs/SiWx917/wifi/ethernetif.h b/src/platform/silabs/SiWx917/wifi/ethernetif.h
new file mode 100644
index 0000000..dfea1ea
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/ethernetif.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "lwip/err.h"
+#include "lwip/netif.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+/***************************************************************************
+ * @fn err_t sta_ethernetif_init(struct netif *netif)
+ * @brief
+ * Sets up the station network interface.
+ *
+ * @param netif the lwip network interface structure
+ * @returns ERR_OK if successful
+ ******************************************************************************/
+err_t sta_ethernetif_init(struct netif * netif);
+
+/***************************************************************************
+ * @fn err_t ap_ethernetif_init(struct netif *netif
+ * @brief
+ * Sets up the AP network interface.
+ *
+ * @param netif the lwip network interface structure
+ * @returns ERR_OK if successful
+ ******************************************************************************/
+err_t ap_ethernetif_init(struct netif * netif);
+
+#ifdef WF200_WIFI
+void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer);
+#else
+void wfx_host_received_sta_frame_cb(uint8_t * buf, int len);
+#endif /* WF200_WIFI */
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp b/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp
new file mode 100644
index 0000000..e19cf97
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp
@@ -0,0 +1,159 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS911X_SOCKETS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#include "wfx_host_events.h"
+#include "wifi_config.h"
+
+#include "AppConfig.h"
+#include "dhcp_client.h"
+#include "ethernetif.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include <platform/CHIPDeviceLayer.h>
+using namespace ::chip;
+using namespace ::chip::DeviceLayer;
+static struct netif sta_netif;
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+static struct netif ap_netif;
+#endif
+
+/****************************************************************************
+ * @fn static void netif_config(struct netif *sta_if, struct netif *ap_if)
+ * @brief
+ * netif configuration
+ * @param[in] sta_if:
+ * @param[in] ap_if:
+ * @return None
+ *****************************************************************************/
+static void netif_config(struct netif * sta_if, struct netif * ap_if)
+{
+ if (sta_if != NULL)
+ {
+#if LWIP_IPV4
+ ip_addr_t sta_ipaddr;
+ ip_addr_t sta_netmask;
+ ip_addr_t sta_gw;
+
+ /* Initialize the Station information */
+ ip_addr_set_zero_ip4(&sta_ipaddr);
+ ip_addr_set_zero_ip4(&sta_netmask);
+ ip_addr_set_zero_ip4(&sta_gw);
+#endif /* LWIP_IPV4 */
+
+ /* Add station interfaces */
+ netif_add(sta_if,
+#if LWIP_IPV4
+ (const ip4_addr_t *) &sta_ipaddr, (const ip4_addr_t *) &sta_netmask, (const ip4_addr_t *) &sta_gw,
+#endif /* LWIP_IPV4 */
+ NULL, &sta_ethernetif_init, &tcpip_input);
+
+ /* Registers the default network interface */
+ netif_set_default(sta_if);
+ }
+}
+
+/****************************************************************************
+ * @fn void wfx_lwip_set_sta_link_up(void)
+ * @brief
+ * Set station link status to up.
+ * @param[in] None
+ * @return None
+ *****************************************************************************/
+void wfx_lwip_set_sta_link_up(void)
+{
+ netifapi_netif_set_up(&sta_netif);
+ netifapi_netif_set_link_up(&sta_netif);
+#if LWIP_IPV4 && LWIP_DHCP
+ dhcpclient_set_link_state(LINK_UP);
+#endif /* LWIP_IPV4 && LWIP_DHCP */
+ /*
+ * Enable IPV6
+ */
+
+#if LWIP_IPV6_AUTOCONFIG
+ sta_netif.ip6_autoconfig_enabled = 1;
+#endif /* LWIP_IPV6_AUTOCONFIG */
+ netif_create_ip6_linklocal_address(&sta_netif, MAC_48_BIT_SET);
+}
+
+/***************************************************************************
+ * @fn void wfx_lwip_set_sta_link_down(void)
+ * @brief
+ * Set station link status to down.
+ * @param[in] None
+ * @return None
+ *****************************************************************************/
+void wfx_lwip_set_sta_link_down(void)
+{
+#if LWIP_IPV4 && LWIP_DHCP
+ dhcpclient_set_link_state(LINK_DOWN);
+#endif /* LWIP_IPV4 && LWIP_DHCP */
+ netifapi_netif_set_link_down(&sta_netif);
+ netifapi_netif_set_down(&sta_netif);
+}
+
+/***************************************************************************
+ * @fn void wfx_lwip_start(void)
+ * @brief
+ * Initialize the LwIP stack
+ * @param[in] None
+ * @return None
+ *****************************************************************************/
+void wfx_lwip_start(void)
+{
+ /* Initialize the LwIP stack */
+ netif_config(&sta_netif, NULL);
+}
+
+/***************************************************************************
+ * @fn struct netif *wfx_get_netif(sl_wfx_interface_t interface)
+ * @brief
+ * get the netif
+ * @param[in] interface:
+ * @return None
+ *****************************************************************************/
+struct netif * wfx_get_netif(sl_wfx_interface_t interface)
+{
+ if (interface == SL_WFX_STA_INTERFACE)
+ {
+ return &sta_netif;
+ }
+#ifdef SL_WFX_CONFIG_SOFTAP
+ else if (interface == SL_WFX_SOFTAP_INTERFACE)
+ {
+ return &ap_netif;
+ }
+#endif
+ return (struct netif *) 0;
+}
+
+#endif /* RS911X_SOCKETS */
diff --git a/src/platform/silabs/SiWx917/wifi/wfx_host_events.h b/src/platform/silabs/SiWx917/wifi/wfx_host_events.h
new file mode 100644
index 0000000..5a7e861
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wfx_host_events.h
@@ -0,0 +1,375 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifdef WF200_WIFI
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "semphr.h"
+#include "task.h"
+#include "timers.h"
+
+#include "sl_wfx_cmd_api.h"
+#include "sl_wfx_constants.h"
+
+typedef struct __attribute__((__packed__)) sl_wfx_get_counters_cnf_body_s
+{
+ uint32_t status;
+ uint16_t mib_id;
+ uint16_t length;
+ uint32_t rcpi;
+ uint32_t count_plcp_errors;
+ uint32_t count_fcs_errors;
+ uint32_t count_tx_packets;
+ uint32_t count_rx_packets;
+ uint32_t count_rx_packet_errors;
+ uint32_t count_rx_decryption_failures;
+ uint32_t count_rx_mic_failures;
+ uint32_t count_rx_no_key_failures;
+ uint32_t count_tx_multicast_frames;
+ uint32_t count_tx_frames_success;
+ uint32_t count_tx_frame_failures;
+ uint32_t count_tx_frames_retried;
+ uint32_t count_tx_frames_multi_retried;
+ uint32_t count_rx_frame_duplicates;
+ uint32_t count_rts_success;
+ uint32_t count_rts_failures;
+ uint32_t count_ack_failures;
+ uint32_t count_rx_multicast_frames;
+ uint32_t count_rx_frames_success;
+ uint32_t count_rx_cmacicv_errors;
+ uint32_t count_rx_cmac_replays;
+ uint32_t count_rx_mgmt_ccmp_replays;
+ uint32_t count_rx_bipmic_errors;
+ uint32_t count_rx_beacon;
+ uint32_t count_miss_beacon;
+ uint32_t reserved[15];
+} sl_wfx_get_counters_cnf_body_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_get_counters_cnf_s
+{
+ /** Common message header. */
+ sl_wfx_header_t header;
+ /** Confirmation message body. */
+ sl_wfx_get_counters_cnf_body_t body;
+} sl_wfx_get_counters_cnf_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_mib_req_body_s
+{
+ uint16_t mib_id; ///< ID of the MIB to be read.
+ uint16_t reserved;
+} sl_wfx_mib_req_body_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_header_mib_s
+{
+ uint16_t length; ///< Message length in bytes including this uint16_t.
+ ///< Maximum value is 8188 but maximum Request size is FW dependent and reported in the
+ ///< ::sl_wfx_startup_ind_body_t::size_inp_ch_buf.
+ uint8_t id; ///< Contains the message Id indexed by sl_wfx_general_commands_ids_t or sl_wfx_message_ids_t.
+ uint8_t reserved : 1;
+ uint8_t interface : 2;
+ uint8_t seqnum : 3;
+ uint8_t encrypted : 2;
+} sl_wfx_header_mib_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_mib_req_s
+{
+ /** Common message header. */
+ sl_wfx_header_mib_t header;
+ /** Request message body. */
+ sl_wfx_mib_req_body_t body;
+} sl_wfx_mib_req_t;
+
+#else /* End WF200 else RS911x */
+
+#include "wfx_msgs.h"
+
+/* Wi-Fi events*/
+#define SL_WFX_STARTUP_IND_ID 1
+#define SL_WFX_CONNECT_IND_ID 2
+#define SL_WFX_DISCONNECT_IND_ID 3
+#define SL_WFX_SCAN_COMPLETE_ID 4
+#define WFX_RSI_SSID_SIZE 64
+
+#endif /* WF200 */
+
+#ifndef RS911X_SOCKETS
+/* LwIP includes. */
+#include "lwip/apps/httpd.h"
+#include "lwip/ip_addr.h"
+#include "lwip/netif.h"
+#include "lwip/netifapi.h"
+#include "lwip/tcpip.h"
+
+/* Wi-Fi bitmask events - for the task */
+#define SL_WFX_CONNECT (1 << 1)
+#define SL_WFX_DISCONNECT (1 << 2)
+#define SL_WFX_START_AP (1 << 3)
+#define SL_WFX_STOP_AP (1 << 4)
+#define SL_WFX_SCAN_START (1 << 5)
+#define SL_WFX_SCAN_COMPLETE (1 << 6)
+#define SL_WFX_RETRY_CONNECT (1 << 7)
+
+#endif /* RS911X_SOCKETS */
+
+#include "sl_status.h"
+
+#ifdef RS911X_WIFI
+#define WLAN_TASK_STACK_SIZE 1024
+#define WLAN_TASK_PRIORITY 1
+#define WLAN_DRIVER_TASK_PRIORITY 1
+#define MAX_JOIN_RETRIES_COUNT 5
+
+#else /* WF200 */
+#define WLAN_TASK_STACK_SIZE 1024
+#define WLAN_TASK_PRIORITY 1
+#define MAX_JOIN_RETRIES_COUNT 5
+#endif
+
+// WLAN related Macros
+#define ETH_FRAME 0
+#define CMP_SUCCESS 0
+#define BSSID_MAX_STR_LEN 6
+#define MAC_ADDRESS_FIRST_OCTET 6
+#define AP_START_SUCCESS 0
+#define BITS_TO_WAIT 0
+#define CONNECTION_STATUS_SUCCESS 1
+#define IP_STATUS_FAIL 0
+#define GET_IPV6_SUCCESS 1
+#define GET_IPV6_FAIL 0
+#define BEACON_1 0
+#define CHANNEL_LIST (const uint8_t *) 0
+#define CHANNEL_COUNT 0
+#define IE_DATA (const uint8_t *) 0
+#define IE_DATA_LENGTH 0
+#define BSSID_SCAN (const uint8_t *) 0
+#define CHANNEL_0 0
+#define PREVENT_ROAMING 1
+#define DISABLE_PMF_MODE 0
+#define STA_IP_FAIL 0
+#define IP_STATUS_SUCCESS 1
+#define ACTIVE_CHANNEL_TIME_100 100
+#define PASSIVE_CHANNEL_TIME_0 0
+#define PROBE_NUM_REQ_1 1
+
+#define PINOUT_CLEAR_STATUS 0
+#define TICKS_TO_WAIT_0 0
+#define TICKS_TO_WAIT_3 3
+#define TICKS_TO_WAIT_1 1
+#define TICKS_TO_WAIT_500 500
+
+// TASK and Interrupt Macros
+#define SUCCESS_STATUS 1
+#define LINK_UP 1
+#define LINK_DOWN 0
+#define MAC_48_BIT_SET 1
+#define STRUCT_PBUF (struct pbuf *) 0
+#define PRIORITY_0 0
+#define HEX_VALUE_FF 0XFF
+
+// Timer Delay
+#define MAX_XLEN 16
+#define MIN_XLEN 0
+#define PINOUT_CLEAR 0
+#define PINOUT_SET 1
+#define WFX_SPI_NVIC_PRIORITY 5
+#define WFX_GPIO_NVIC_PRIORITY 5
+#define CB_VALUE (DMADRV_Callback_t) 0
+
+/* TIMER_TICKS_TO_WAIT Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the start command to be successfully
+ * sent to the timer command queue.
+ */
+#define TIMER_TICKS_TO_WAIT_0 0
+
+#define CONVERT_SEC_TO_MSEC 1000
+#define CONVERT_USEC_TO_MSEC (1 / 1000)
+
+#define RSI_RESPONSE_MAX_SIZE 28
+#define RSI_RESPONSE_HOLD_BUFF_SIZE 128
+#define RSI_DRIVER_STATUS 0
+#define OPER_MODE_0 0
+#define COEX_MODE_0 0
+#define RESP_BUFF_SIZE 6
+#define AP_CHANNEL_NO_0 0
+#define SCAN_BITMAP_OPTN_1 1
+#define IP_CONF_RSP_BUFF_LENGTH_4 4
+#define STATION 0
+#define BG_SCAN_RES_SIZE 500
+
+#define SPI_CONFIG_SUCCESS 0
+#define WPA3_SECURITY 3
+
+typedef enum
+{
+ WIFI_EVENT,
+ IP_EVENT,
+} wfx_event_base_t;
+
+typedef enum
+{
+ IP_EVENT_STA_GOT_IP,
+ IP_EVENT_GOT_IP6,
+ IP_EVENT_STA_LOST_IP,
+} ip_event_id_t;
+
+/* Note that these are same as RSI_security */
+typedef enum
+{
+ WFX_SEC_NONE = 0,
+ WFX_SEC_WPA = 1,
+ WFX_SEC_WPA2 = 2,
+ WFX_SEC_WEP = 3,
+ WFX_SEC_WPA_EAP = 4,
+ WFX_SEC_WPA2_EAP = 5,
+ WFX_SEC_WPA_WPA2_MIXED = 6,
+ WFX_SEC_WPA_PMK = 7,
+ WFX_SEC_WPA2_PMK = 8,
+ WFX_SEC_WPS_PIN = 9,
+ WFX_SEC_GEN_WPS_PIN = 10,
+ WFX_SEC_PUSH_BTN = 11,
+ WFX_SEC_WPA3 = 11,
+} wfx_sec_t;
+
+#define WPA3_SECURITY 3
+
+typedef struct
+{
+ char ssid[32 + 1];
+ char passkey[64 + 1];
+ uint8_t security;
+} wfx_wifi_provision_t;
+
+typedef enum
+{
+ WIFI_MODE_NULL = 0,
+ WIFI_MODE_STA,
+ WIFI_MODE_AP,
+ WIFI_MODE_APSTA,
+ WIFI_MODE_MAX,
+} wifi_mode_t;
+
+typedef struct wfx_wifi_scan_result
+{
+ char ssid[32 + 1];
+ uint8_t security;
+ uint8_t bssid[6];
+ uint8_t chan;
+ int16_t rssi; /* I suspect this is in dBm - so signed */
+} wfx_wifi_scan_result_t;
+
+typedef struct wfx_wifi_scan_ext
+{
+ uint32_t beacon_lost_count;
+ uint32_t beacon_rx_count;
+ uint32_t mcast_rx_count;
+ uint32_t mcast_tx_count;
+ uint32_t ucast_rx_count;
+ uint32_t ucast_tx_count;
+ uint32_t overrun_count;
+} wfx_wifi_scan_ext_t;
+
+#ifdef RS911X_WIFI
+/*
+ * This Sh%t is here to support WFXUtils - and the Matter stuff that uses it
+ * We took it from the SDK (for WF200)
+ */
+typedef enum
+{
+ SL_WFX_NOT_INIT = 0,
+ SL_WFX_STARTED = 1,
+ SL_WFX_STA_INTERFACE_CONNECTED = 2,
+ SL_WFX_AP_INTERFACE_UP = 3,
+ SL_WFX_SLEEPING = 4,
+ SL_WFX_POWER_SAVE_ACTIVE = 5,
+} sl_wfx_state_t;
+
+typedef enum
+{
+ SL_WFX_STA_INTERFACE = 0, ///< Interface 0, linked to the station
+ SL_WFX_SOFTAP_INTERFACE = 1, ///< Interface 1, linked to the softap
+} sl_wfx_interface_t;
+
+#endif /* RS911X_WIFI */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void sl_wfx_host_gpio_init(void);
+sl_status_t wfx_wifi_start(void);
+void wfx_enable_sta_mode(void);
+sl_wfx_state_t wfx_get_wifi_state(void);
+void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr);
+void wfx_set_wifi_provision(wfx_wifi_provision_t * wifiConfig);
+bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig);
+bool wfx_is_sta_provisioned(void);
+bool wfx_is_sta_mode_enabled(void);
+int32_t wfx_get_ap_info(wfx_wifi_scan_result_t * ap);
+int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t * extra_info);
+int32_t wfx_reset_counts();
+
+void wfx_clear_wifi_provision(void);
+sl_status_t wfx_connect_to_ap(void);
+void wfx_setup_ip6_link_local(sl_wfx_interface_t);
+bool wfx_is_sta_connected(void);
+sl_status_t wfx_sta_discon(void);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+bool wfx_have_ipv4_addr(sl_wfx_interface_t);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+bool wfx_have_ipv6_addr(sl_wfx_interface_t);
+wifi_mode_t wfx_get_wifi_mode(void);
+bool wfx_start_scan(char * ssid, void (*scan_cb)(wfx_wifi_scan_result_t *)); /* true returned if successfully started */
+void wfx_cancel_scan(void);
+
+/*
+ * Call backs into the Matter Platform code
+ */
+void wfx_started_notify(void);
+void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap);
+void wfx_disconnected_notify(int32_t status);
+/* Implemented for LWIP */
+void wfx_host_received_sta_frame_cb(uint8_t * buf, int len);
+void wfx_lwip_set_sta_link_up(void);
+void wfx_lwip_set_sta_link_down(void);
+void wfx_lwip_start(void);
+struct netif * wfx_get_netif(sl_wfx_interface_t interface);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+void wfx_dhcp_got_ipv4(uint32_t);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+bool wfx_hw_ready(void);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+void wfx_ip_changed_notify(int got_ip);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+void wfx_ipv6_notify(int got_ip);
+
+#ifdef RS911X_WIFI
+/* RSI for LWIP */
+void * wfx_rsi_alloc_pkt(void);
+void wfx_rsi_pkt_add_data(void * p, uint8_t * buf, uint16_t len, uint16_t off);
+int32_t wfx_rsi_send_data(void * p, uint16_t len);
+#endif /* RS911X_WIFI */
+
+#ifdef WF200_WIFI
+void wfx_bus_start(void);
+sl_status_t get_all_counters(void);
+void sl_wfx_host_gpio_init(void);
+sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload);
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/platform/silabs/SiWx917/wifi/wfx_msgs.h b/src/platform/silabs/SiWx917/wifi/wfx_msgs.h
new file mode 100644
index 0000000..edf0aec
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wfx_msgs.h
@@ -0,0 +1,182 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WFX_MSGS_H_
+#define _WFX_MSGS_H_
+/*
+ * Taken from sl_wfx firmware - so I can re-use.
+ * I need to do a better job than to use this stuff
+ * in the CPP files of Matter
+ */
+typedef struct
+{
+ uint8_t octet[6]; ///< Table to store a MAC address
+} sl_wfx_mac_address_t;
+/**
+ * @brief General Message header structure
+ *
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_header_s
+{
+ uint16_t length; ///< Message length in bytes including this uint16_t.
+ ///< Maximum value is 8188 but maximum Request size is FW dependent and reported in the
+ ///< ::sl_wfx_startup_ind_body_t::size_inp_ch_buf.
+ uint8_t id; ///< Contains the message Id indexed by sl_wfx_general_commands_ids_t or sl_wfx_message_ids_t.
+ uint8_t info; ///< TODO comment missing
+} sl_wfx_header_t;
+
+/**
+ * @brief Generic message structure for all requests, confirmations and indications
+ *
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_generic_message_s
+{
+ sl_wfx_header_t header; ///< 4 bytes header
+ uint8_t body[]; ///< variable size payload of the message
+} sl_wfx_generic_message_t;
+#define SL_WFX_OPN_SIZE 14
+#define SL_WFX_UID_SIZE 8
+#define SL_WFX_DISABLED_CHANNEL_LIST_SIZE 2
+#define SL_WFX_FIRMWARE_LABEL_SIZE 128
+/**
+ * @brief Startup Indication message.
+ * This is the first message sent to the host to confirm boot success.
+ * It gives detailed information on the HW and FW versions and capabilities
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_startup_ind_body_s
+{
+ uint32_t
+ status; ///< Initialization status. A value of zero indicates the boot is completed successfully (see enum sl_wfx_status_t)
+ uint16_t hardware_id; ///<=RO misc_read_reg7 register value
+#if 0 /* Not used in RS911x for now - use stuff here for the port */
+ uint8_t opn[SL_WFX_OPN_SIZE]; ///<=OTP part_OPN
+ uint8_t uid[SL_WFX_UID_SIZE]; ///<=OTP UID
+ uint16_t num_inp_ch_bufs; ///<Number of buffers available for request messages.
+ uint16_t size_inp_ch_buf; ///<TX Buffer size in bytes=request message max size.
+ uint8_t num_links_aP; ///<number of STA that are supported in AP mode
+ uint8_t num_interfaces; ///<number of interfaces (WIFI link : STA or AP) that can be created by the user
+ uint8_t mac_addr[2][SL_WFX_MAC_ADDR_SIZE]; ///<MAC addresses derived from OTP
+ uint8_t api_version_minor;
+ uint8_t api_version_major;
+ sl_wfx_capabilities_t capabilities; ///<List some FW options
+ uint8_t firmware_build;
+ uint8_t firmware_minor;
+ uint8_t firmware_major;
+ uint8_t firmware_type; ///<See enum sl_wfx_fw_type_t
+ uint8_t disabled_channel_list[SL_WFX_DISABLED_CHANNEL_LIST_SIZE]; ///<=OTP Disabled channel list info
+ sl_wfx_otp_regul_sel_mode_info_t regul_sel_mode_info; ///<OTP region selection mode info
+ sl_wfx_otp_phy_info_t otp_phy_info; ///<info on OTP backoff tables used to enforce the different DFS regulations.
+ uint32_t supported_rate_mask; ///<A bit mask that indicates which rates are supported by the Physical layer. See enum api_rate_index.
+ uint8_t firmware_label[SL_WFX_FIRMWARE_LABEL_SIZE]; ///<Null terminated text string describing the loaded FW.
+#else
+ uint8_t mac_addr[6];
+#endif
+} sl_wfx_startup_ind_body_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_startup_ind_s
+{
+ sl_wfx_header_t header;
+ sl_wfx_startup_ind_body_t body;
+} sl_wfx_startup_ind_t;
+/**
+ * @brief Indication message body for sl_wfx_connect_ind_t.
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_connect_ind_body_s
+{
+ /**
+ * @brief Status of the connection request.
+ * @details <B>WFM_STATUS_SUCCESS</B>: the connection request was completed successfully.
+ * <BR><B>any other value</B>: the connection request failed.
+ * <BR>See sl_wfx_fmac_status_t for enumeration values.
+ */
+ uint32_t status;
+ /**
+ * @brief MAC address of the connected access point.
+ */
+ uint8_t mac[6];
+ /**
+ * @brief Channel of the connected access point.
+ * @details <B>1 - 13</B>: Channel number.
+ */
+ uint16_t channel;
+ /**
+ * @brief Beacon Interval of the connected access point.
+ */
+ uint8_t beacon_interval;
+ /**
+ * @brief DTIM period of the connected access point.
+ * @details <B>1 - 255</B>: DTIM period.
+ */
+ uint8_t dtim_period;
+ /**
+ * @brief Maximum PHY data rate supported by the connection.
+ * @details See sl_wfx_rate_index_t for enumeration values.
+ */
+ uint16_t max_phy_rate;
+} sl_wfx_connect_ind_body_t;
+
+/**
+ * @brief Indication message used to signal the completion of a connection operation.
+ * @details The device will send this indication to signal the connection request initiated
+ * with sl_wfx_connect_req_t has been completed. The indication is also sent when
+ * the device autonomously roams to another access point.
+ * @ingroup WFM_GROUP_MODE_IDLE
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_connect_ind_s
+{
+ /** Common message header. */
+ sl_wfx_header_t header;
+ /** Indication message body. */
+ sl_wfx_connect_ind_body_t body;
+} sl_wfx_connect_ind_t;
+/**
+ * @brief Indication message body for sl_wfx_disconnect_ind_t.
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_disconnect_ind_body_s
+{
+ /**
+ * @brief MAC address of the access point.
+ */
+ uint8_t mac[6];
+ /**
+ * @brief Reason for disconnection.
+ * @details <B>WFM_DISCONNECTED_REASON_UNSPECIFIED</B>: The device disconnected because of an internal error.
+ * <BR><B>WFM_DISCONNECTED_REASON_AP_LOST</B>: The device lost the AP beacons for too long.
+ * <BR><B>WFM_DISCONNECTED_REASON_REJECTED</B>: The device was disconnected by the AP.
+ * <BR><B>WFM_DISCONNECTED_REASON_LEAVING_BSS</B>: Disconnection was requested through the device API.
+ * <BR><B>WFM_DISCONNECTED_REASON_WPA_COUNTERMEASURES</B>: WPA countermeasures triggered a disconnection
+ * <BR>See sl_wfx_disconnected_reason_t for enumeration values.
+ */
+ uint16_t reason;
+} sl_wfx_disconnect_ind_body_t;
+
+/**
+ * @brief Indication message used to signal the completion of a disconnection operation.
+ * @details The device will send this indication to signal the disconnection request initiated
+ * with sl_wfx_disconnect_req_t has been completed. The indication is also sent when
+ * the device has lost the connection to an access point and has been unable to regain it.
+ * @ingroup WFM_GROUP_MODE_STA
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_disconnect_ind_s
+{
+ /** Common message header. */
+ sl_wfx_header_t header;
+ /** Indication message body. */
+ sl_wfx_disconnect_ind_body_t body;
+} sl_wfx_disconnect_ind_t;
+
+#endif /* _WFX_MSGS_H_ */
diff --git a/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp
new file mode 100644
index 0000000..9f681e7
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp
@@ -0,0 +1,189 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+
+#include "AppConfig.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+
+#ifdef RS911X_WIFI
+#include "wfx_rsi.h"
+#endif
+
+#include <platform/CHIPDeviceLayer.h>
+//#include <app/server/Mdns.h>
+#include <app/server/Dnssd.h>
+#include <app/server/Server.h>
+
+using namespace ::chip;
+using namespace ::chip::DeviceLayer;
+
+/*
+ * Notifications to the upper-layer
+ * All done in the context of the RSI/WiFi task (rsi_if.c)
+ */
+
+/***********************************************************************************
+ * @fn wfx_started_notify()
+ * @brief
+ * Wifi device started notification
+ * @param[in]: None
+ * @return None
+ *************************************************************************************/
+void wfx_started_notify()
+{
+ sl_wfx_startup_ind_t evt;
+ sl_wfx_mac_address_t mac;
+
+ SILABS_LOG("%s: started.", __func__);
+
+ memset(&evt, 0, sizeof(evt));
+ evt.header.id = SL_WFX_STARTUP_IND_ID;
+ evt.header.length = sizeof evt;
+ evt.body.status = 0;
+ wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac);
+ memcpy(&evt.body.mac_addr[0], &mac.octet[0], MAC_ADDRESS_FIRST_OCTET);
+
+ PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
+}
+
+/***********************************************************************************
+ * @fn void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t *ap)
+ * @brief
+ * For now we are not notifying anything other than AP Mac -
+ * Other stuff such as DTIM etc. may be required for later
+ * @param[in] status:
+ * @param[in] ap: access point
+ * @return None
+ *************************************************************************************/
+void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap)
+{
+ sl_wfx_connect_ind_t evt;
+
+ SILABS_LOG("%s: started.", __func__);
+
+ if (status != SUCCESS_STATUS)
+ {
+ SILABS_LOG("%s: error: failed status: %d.", __func__, status);
+ return;
+ }
+
+ SILABS_LOG("%s: connected.", __func__);
+
+ memset(&evt, 0, sizeof(evt));
+ evt.header.id = SL_WFX_CONNECT_IND_ID;
+ evt.header.length = sizeof evt;
+
+#ifdef RS911X_WIFI
+ evt.body.channel = wfx_rsi.ap_chan;
+#endif
+ memcpy(&evt.body.mac[0], &ap->octet[0], MAC_ADDRESS_FIRST_OCTET);
+
+ PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
+}
+
+/**************************************************************************************
+ * @fn void wfx_disconnected_notify(int32_t status)
+ * @brief
+ * notification of disconnection
+ * @param[in] status:
+ * @return None
+ ********************************************************************************************/
+void wfx_disconnected_notify(int32_t status)
+{
+ sl_wfx_disconnect_ind_t evt;
+
+ SILABS_LOG("%s: started.", __func__);
+
+ memset(&evt, 0, sizeof(evt));
+ evt.header.id = SL_WFX_DISCONNECT_IND_ID;
+ evt.header.length = sizeof evt;
+ evt.body.reason = status;
+ PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
+}
+
+/**************************************************************************************
+ * @fn void wfx_ipv6_notify(int got_ip)
+ * @brief
+ * notification of ipv6
+ * @param[in] got_ip:
+ * @return None
+ ********************************************************************************************/
+void wfx_ipv6_notify(int got_ip)
+{
+ sl_wfx_generic_message_t eventData;
+
+ SILABS_LOG("%s: started.", __func__);
+
+ memset(&eventData, 0, sizeof(eventData));
+ eventData.header.id = got_ip ? IP_EVENT_GOT_IP6 : IP_EVENT_STA_LOST_IP;
+ eventData.header.length = sizeof(eventData.header);
+ PlatformMgrImpl().HandleWFXSystemEvent(IP_EVENT, &eventData);
+
+ /* So the other threads can run and have the connectivity OK */
+ if (got_ip)
+ {
+ /* Should remember this */
+ vTaskDelay(1);
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::DnssdServer::Instance().StartServer(/*Dnssd::CommissioningMode::kEnabledBasic*/);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+ }
+}
+
+/**************************************************************************************
+ * @fn void wfx_ip_changed_notify(int got_ip)
+ * @brief
+ * notification of ip change
+ * @param[in] got_ip:
+ * @return None
+ ********************************************************************************************/
+void wfx_ip_changed_notify(int got_ip)
+{
+ sl_wfx_generic_message_t eventData;
+
+ SILABS_LOG("%s: started.", __func__);
+
+ memset(&eventData, 0, sizeof(eventData));
+ eventData.header.id = got_ip ? IP_EVENT_STA_GOT_IP : IP_EVENT_STA_LOST_IP;
+ eventData.header.length = sizeof(eventData.header);
+ PlatformMgrImpl().HandleWFXSystemEvent(IP_EVENT, &eventData);
+
+ /* So the other threads can run and have the connectivity OK */
+ if (got_ip)
+ {
+ /* Should remember this */
+ vTaskDelay(1);
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::DnssdServer::Instance().StartServer(/*Dnssd::CommissioningMode::kEnabledBasic*/);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+ }
+}
diff --git a/src/platform/silabs/SiWx917/wifi/wifi_config.h b/src/platform/silabs/SiWx917/wifi/wifi_config.h
new file mode 100644
index 0000000..88ad34b
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wifi_config.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DEMO_CONFIG_H
+#define DEMO_CONFIG_H
+
+#define USE_DHCP_CLIENT_DEFAULT 1 ///< If defined, DHCP is enabled, otherwise static address below is used
+
+/************************** Station Static Default ****************************/
+#define STA_IP_ADDR0_DEFAULT (uint8_t) 192 ///< Static IP: IP address value 0
+#define STA_IP_ADDR1_DEFAULT (uint8_t) 168 ///< Static IP: IP address value 1
+#define STA_IP_ADDR2_DEFAULT (uint8_t) 0 ///< Static IP: IP address value 2
+#define STA_IP_ADDR3_DEFAULT (uint8_t) 1 ///< Static IP: IP address value 3
+
+/*NETMASK*/
+#define STA_NETMASK_ADDR0_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 0
+#define STA_NETMASK_ADDR1_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 1
+#define STA_NETMASK_ADDR2_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 2
+#define STA_NETMASK_ADDR3_DEFAULT (uint8_t) 0 ///< Static IP: Netmask value 3
+
+/*Gateway Address*/
+#define STA_GW_ADDR0_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 0
+#define STA_GW_ADDR1_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 1
+#define STA_GW_ADDR2_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 2
+#define STA_GW_ADDR3_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 3
+
+/************************** Access Point Static Default ****************************/
+// #define AP_IP_ADDR0_DEFAULT (uint8_t) 10 ///< Static IP: IP address value 0
+// #define AP_IP_ADDR1_DEFAULT (uint8_t) 10 ///< Static IP: IP address value 1
+// #define AP_IP_ADDR2_DEFAULT (uint8_t) 0 ///< Static IP: IP address value 2
+// #define AP_IP_ADDR3_DEFAULT (uint8_t) 1 ///< Static IP: IP address value 3
+
+/*NETMASK*/
+// #define AP_NETMASK_ADDR0_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 0
+// #define AP_NETMASK_ADDR1_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 1
+// #define AP_NETMASK_ADDR2_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 2
+// #define AP_NETMASK_ADDR3_DEFAULT (uint8_t) 0 ///< Static IP: Netmask value 3
+
+/*Gateway Address*/
+// #define AP_GW_ADDR0_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 0
+// #define AP_GW_ADDR1_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 1
+// #define AP_GW_ADDR2_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 2
+// #define AP_GW_ADDR3_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 3
+
+#define WLAN_SSID_DEFAULT "AP_name" ///< wifi ssid for client mode
+#define WLAN_PASSKEY_DEFAULT "passkey" ///< wifi password for client mode
+#define WLAN_SECURITY_DEFAULT WFM_SECURITY_MODE_WPA2_PSK ///< wifi security mode for client mode:
+///< WFM_SECURITY_MODE_OPEN/WFM_SECURITY_MODE_WEP/WFM_SECURITY_MODE_WPA2_WPA1_PSK
+
+#define SOFTAP_SSID_DEFAULT "silabs_softap" ///< wifi ssid for soft ap mode
+#define SOFTAP_PASSKEY_DEFAULT "changeme" ///< wifi password for soft ap mode
+#define SOFTAP_SECURITY_DEFAULT WFM_SECURITY_MODE_WPA2_PSK ///< wifi security for soft ap mode:
+///< WFM_SECURITY_MODE_OPEN/WFM_SECURITY_MODE_WEP/WFM_SECURITY_MODE_WPA2_WPA1_PSK
+
+#define SOFTAP_CHANNEL_DEFAULT 6 ///< wifi channel for soft ap
+
+#endif // DEMO_CONFIG_H
diff --git a/src/platform/silabs/SiWx917/wifi_args.gni b/src/platform/silabs/SiWx917/wifi_args.gni
new file mode 100644
index 0000000..73a6613
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi_args.gni
@@ -0,0 +1,58 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+
+# ARM architecture flags will be set based on silabs_family.
+arm_platform_config = "${efr32_sdk_build_root}/efr32_arm.gni"
+
+mbedtls_target = "${efr32_sdk_build_root}:efr32_sdk"
+
+# default to platform crypto implementation but allow commandline override
+if (chip_crypto == "") {
+ chip_crypto = "platform"
+}
+
+# Transitional CommissionableDataProvider not used anymore
+# examples/platform/efr32/EFR32DeviceDataProvider is now used.
+chip_use_transitional_commissionable_data_provider = false
+
+#lwip_platform = "external"
+lwip_platform = "efr32"
+lwip_ipv6 = true
+lwip_ipv4 = true
+lwip_api = true
+lwip_ethernet = true
+
+chip_device_platform = "efr32"
+chip_enable_openthread = false
+chip_inet_config_enable_ipv4 = true
+chip_inet_config_enable_dns_resolver = false
+chip_inet_config_enable_tcp_endpoint = true
+
+chip_build_tests = false
+chip_config_memory_management = "platform"
+chip_mdns = "minimal"
+chip_enable_pw_rpc = false
+
+pw_build_LINK_DEPS = [
+ "$dir_pw_assert:impl",
+ "$dir_pw_log:impl",
+]
diff --git a/third_party/silabs/SiWx917_sdk.gni b/third_party/silabs/SiWx917_sdk.gni
new file mode 100644
index 0000000..38359a7
--- /dev/null
+++ b/third_party/silabs/SiWx917_sdk.gni
@@ -0,0 +1,825 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/jlink.gni")
+import("//build_overrides/mbedtls.gni")
+
+import("${chip_root}/src/lib/lib.gni")
+import("silabs_board.gni")
+
+declare_args() {
+ # Location of the efr32 SDK.
+ efr32_sdk_root = "${chip_root}/third_party/silabs/gecko_sdk"
+ sdk_support_root = "${chip_root}/third_party/silabs/matter_support"
+
+ # Build openthread with prebuilt silabs lib
+ use_silabs_thread_lib = false
+ enable_openthread_cli = true
+
+ kvs_max_entries = 75
+ use_external_flash = true
+
+ # Use Silabs factory data provider example.
+ # Users can implement their own.
+ use_efr32_factory_data_provider = true
+
+ # Enable Segger System View
+ use_system_view = false
+}
+
+# Explorer Kit and MGM240L do not have external flash
+if (silabs_board == "BRD2703A" || silabs_board == "BRD4319A") {
+ use_external_flash = false
+}
+
+# Enable LEDs by default
+use_wstk_leds = true
+
+# Board does not support LEDs and Buttons at the same time
+if (silabs_board == "BRD4317A" || silabs_board == "BRD4316A" ||
+ silabs_board == "BRD4319A") {
+ use_wstk_leds = false
+}
+
+assert(efr32_sdk_root != "", "efr32_sdk_root must be specified")
+
+# Defines an efr32 SDK build target.
+#
+# Parameters:
+# efr32_sdk_root - The location of the erf32 SDK.
+# sources - The sources files to build.
+template("efr32_sdk") {
+ if (defined(invoker.efr32_sdk_root)) {
+ efr32_sdk_root = invoker.efr32_sdk_root
+ }
+
+ assert(efr32_sdk_root != "", "efr32_sdk_root must be specified")
+ use_wf200 = false
+ if (defined(invoker.use_wf200)) {
+ if (invoker.use_wf200) {
+ use_wf200 = true
+ }
+ }
+
+ sdk_target_name = target_name
+
+ config("${sdk_target_name}_config") {
+ include_dirs = []
+ libs = []
+ if (defined(invoker.include_dirs)) {
+ include_dirs += invoker.include_dirs
+ }
+
+ # Treat these includes as system includes, so warnings in them are not fatal.
+ _include_dirs = [
+ "${efr32_sdk_root}",
+ "${efr32_sdk_root}/hardware/kit/common/bsp",
+ "${efr32_sdk_root}/app/common/util/app_assert/",
+ "${efr32_sdk_root}/hardware/board/inc",
+ "${efr32_sdk_root}/hardware/driver/memlcd/inc",
+ "${efr32_sdk_root}/hardware/driver/memlcd/src/ls013b7dh03",
+ "${efr32_sdk_root}/platform/bootloader",
+ "${efr32_sdk_root}/platform/bootloader/config",
+ "${efr32_sdk_root}/platform/bootloader/config/s2/btl_interface",
+ "${efr32_sdk_root}/platform/bootloader/api",
+ "${efr32_sdk_root}/platform/CMSIS/Core/Include",
+ "${efr32_sdk_root}/platform/CMSIS/RTOS2/Include",
+ "${efr32_sdk_root}/platform/common/inc",
+ "${efr32_sdk_root}/platform/driver/button/inc",
+ "${efr32_sdk_root}/platform/emdrv/common/inc",
+ "${efr32_sdk_root}/platform/emdrv/gpiointerrupt/inc",
+ "${efr32_sdk_root}/platform/emdrv/dmadrv/config",
+ "${efr32_sdk_root}/platform/emdrv/dmadrv/inc",
+ "${efr32_sdk_root}/platform/emdrv/nvm3/inc",
+ "${efr32_sdk_root}/platform/emdrv/rtcdrv/inc",
+ "${efr32_sdk_root}/platform/emlib/inc",
+ "${efr32_sdk_root}/platform/halconfig/inc/hal-config",
+ "${efr32_sdk_root}/platform/peripheral/inc",
+ "${efr32_sdk_root}/platform/radio/rail_lib/common",
+ "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32",
+ "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/rf/common/cortex",
+ "${efr32_sdk_root}/platform/radio/rail_lib/hal",
+ "${efr32_sdk_root}/platform/radio/rail_lib/hal/efr32",
+ "${efr32_sdk_root}/platform/radio/rail_lib/protocol/ieee802154",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_pti",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_rf_path",
+ "${efr32_sdk_root}/platform/service/device_init/inc",
+ "${efr32_sdk_root}/platform/service/hfxo_manager/config/",
+ "${efr32_sdk_root}/platform/service/hfxo_manager/inc",
+ "${efr32_sdk_root}/platform/service/hfxo_manager/src",
+ "${efr32_sdk_root}/platform/service/mpu/inc",
+ "${efr32_sdk_root}/platform/service/power_manager/config/",
+ "${efr32_sdk_root}/platform/service/power_manager/inc/",
+ "${efr32_sdk_root}/platform/service/power_manager/src/",
+ "${efr32_sdk_root}/platform/service/sleeptimer/inc",
+ "${efr32_sdk_root}/platform/service/sleeptimer/config",
+ "${efr32_sdk_root}/platform/service/system/inc",
+ "${efr32_sdk_root}/platform/service/udelay/inc",
+ "${efr32_sdk_root}/platform/service/legacy_hal/inc",
+ "${efr32_sdk_root}/platform/service/token_manager/config",
+ "${efr32_sdk_root}/platform/service/token_manager/inc",
+ "${efr32_sdk_root}/platform/service/token_manager/test",
+ "${efr32_sdk_root}/platform/service/token_manager/test/include",
+ "${efr32_sdk_root}/platform/service/token_manager/test/stack/config",
+ "${efr32_sdk_root}/platform/service/token_manager/test/stack/include",
+ "${efr32_sdk_root}/platform/middleware/glib",
+ "${efr32_sdk_root}/platform/middleware/glib/glib",
+ "${efr32_sdk_root}/platform/middleware/glib/dmd",
+ "${efr32_sdk_root}/platform/base/hal/plugin/psstore",
+ "${efr32_sdk_root}/platform/base/hal/plugin/antenna",
+ "${efr32_sdk_root}/protocol/bluetooth/inc/",
+ "${efr32_sdk_root}/app/bluetooth/common/in_place_ota_dfu/",
+ "${efr32_sdk_root}/util/plugin/plugin-common/fem-control",
+ "${efr32_sdk_root}/util/silicon_labs/silabs_core/graphics",
+ "${efr32_sdk_root}/util/silicon_labs/silabs_core/memory_manager",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/include",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/include/psa",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_alt/include",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/inc",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/config/",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/inc",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/inc/public",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/inc",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/",
+ "${efr32_sdk_root}/util/third_party/freertos/cmsis/Include",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/include",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/config",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen",
+ ]
+
+ # Note that we're setting the mbedTLS and PSA configuration files through a
+ # define. This means the build system by default does not pick up changes in
+ # the content of these, only when changing the filename itself.
+ # To fix this, these files are also manually depended upon in the source set
+ # declared in efr32_mbedtls_config further down this file.
+ defines = [
+ "MBEDTLS_CONFIG_FILE=\"efr32-chip-mbedtls-config.h\"",
+ "MBEDTLS_PSA_CRYPTO_CONFIG_FILE=\"efr32-mbedtls-psa-crypto-config.h\"",
+ "__STARTUP_CLEAR_BSS",
+ "HARD_FAULT_LOG_ENABLE",
+ "CORTEXM3_EFM32_MICRO",
+ "EFR32_LOG_ENABLED=1",
+ "NVM3_DEFAULT_NVM_SIZE=40960",
+ "NVM3_DEFAULT_MAX_OBJECT_SIZE=4092",
+ "KVS_MAX_ENTRIES=${kvs_max_entries}",
+ "EFR32_OPENTHREAD_API",
+ "PHY=EMBER_PHY_RAIL",
+ "CORTEXM3",
+ "MICRO=EMBER_MICRO_CORTEXM3_EFR32",
+ "PLAT=EMBER_PLATFORM_CORTEXM3",
+ "${silabs_mcu}=1",
+ "${silabs_board}=1",
+ "__HEAP_SIZE=0",
+ "SL_CATALOG_FREERTOS_KERNEL_PRESENT=1",
+ "MBEDTLS_THREADING_C=1",
+ "MBEDTLS_THREADING_ALT=1",
+ "SL_THREADING_ALT=1",
+ "SL_COMPONENT_CATALOG_PRESENT",
+ "PLATFORM_HEADER=\"platform-header.h\"",
+ "USE_NVM3=1",
+
+ #"__STACK_SIZE=0",
+ ]
+
+ if (use_system_view) {
+ _include_dirs += [
+ "${efr32_sdk_root}/util/third_party/segger/systemview/SEGGER",
+ "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10/Config/Cortex-M",
+ "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10",
+ "${efr32_sdk_root}/util/third_party/segger/systemview/Config/",
+ ]
+
+ defines += [ "SL_SYSTEM_VIEW=1" ]
+ }
+
+ defines += board_defines
+
+ if (use_wstk_leds) {
+ _include_dirs += [ "${efr32_sdk_root}/platform/driver/leddrv/inc" ]
+
+ defines += [ "ENABLE_WSTK_LEDS" ]
+ }
+
+ if (defined(invoker.enable_sleepy_device)) {
+ if (invoker.enable_sleepy_device) {
+ defines += [
+ "CHIP_DEVICE_CONFIG_ENABLE_SED=1",
+ "SL_CATALOG_POWER_MANAGER_PRESENT",
+ "SL_CATALOG_SLEEPTIMER_PRESENT",
+ ]
+ }
+ }
+
+ if (chip_build_libshell) { # matter shell
+ defines += [
+ "ENABLE_CHIP_SHELL",
+ "OPENTHREAD_CONFIG_CLI_TRANSPORT=OT_CLI_TRANSPORT_CONSOLE",
+ "CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI=1",
+ ]
+ } else {
+ if (enable_openthread_cli) { # ot-cli only
+ defines += [ "CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI=1" ]
+ }
+ }
+
+ # USART include files
+ if ((defined(invoker.chip_enable_pw_rpc) && invoker.chip_enable_pw_rpc) ||
+ chip_build_libshell || enable_openthread_cli ||
+ (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) ||
+ (defined(invoker.show_qr_code) && invoker.show_qr_code) ||
+ (defined(invoker.disable_lcd) && !invoker.disable_lcd) ||
+ (defined(invoker.use_external_flash) && use_external_flash)) {
+ defines += [ "CONFIG_ENABLE_UART" ]
+
+ if (defined(invoker.use_external_flash) && use_external_flash) {
+ defines += [ "CONFIG_USE_EXTERNAL_FLASH" ]
+
+ _include_dirs += [ "${efr32_sdk_root}/hardware/driver/mx25_flash_shutdown/inc/sl_mx25_flash_shutdown_usart" ]
+ }
+
+ _include_dirs += [
+ "${efr32_sdk_root}/platform/emdrv/uartdrv/inc",
+ "${efr32_sdk_root}/platform/emdrv/uartdrv/config",
+ "${efr32_sdk_root}/hardware/driver/memlcd/inc/memlcd_usart",
+ ]
+ }
+
+ if (silabs_family == "efr32mg12") {
+ _include_dirs += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG12P/Include",
+ "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg1x",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM4F",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg1x/config",
+ "${efr32_sdk_root}/platform/service/device_init/config/s1/",
+ "${efr32_sdk_root}/platform/emdrv/spidrv/inc",
+ ]
+
+ libs += [
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG12P/GCC/binapploader.o",
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG12P/GCC/libbluetooth.a",
+ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg12_gcc_release.a",
+ "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a",
+ ]
+
+ defines += [ "EFR32MG12" ]
+ } else if (silabs_family == "efr32mg21") {
+ _include_dirs += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG21/Include",
+ "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg2x",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg21",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg21/config",
+ "${efr32_sdk_root}/platform/service/device_init/config/s2/",
+ ]
+
+ libs += [
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG21/GCC/binapploader.o",
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG21/GCC/libbluetooth.a",
+ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg21_gcc_release.a",
+ "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a",
+ ]
+
+ defines += [
+ "EFR32MG21",
+ "EFR32_SERIES2_CONFIG1_MICRO",
+ ]
+ } else if (silabs_family == "efr32mg24") {
+ _include_dirs += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG24/Include",
+ "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg2x",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24/config",
+ "${efr32_sdk_root}/platform/service/device_init/config/s2/",
+ "${efr32_sdk_root}/platform/emdrv/spidrv/inc",
+ ]
+
+ libs += [
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libapploader.a",
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libbluetooth.a",
+ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg24_gcc_release.a",
+ "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a",
+ ]
+
+ defines += [
+ "EFR32MG24",
+ "EFR32_SERIES2_CONFIG4_MICRO",
+ ]
+ } else if (silabs_family == "mgm24") {
+ _include_dirs += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Include",
+ "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg2x",
+ "${efr32_sdk_root}/platform/radio/rail_lib/protocol/ble",
+ "${efr32_sdk_root}/platform/radio/rail_lib/protocol/ieee802154",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24/config",
+ "${efr32_sdk_root}/platform/service/device_init/config/s2/",
+ ]
+
+ libs += [
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libapploader.a",
+ "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libbluetooth.a",
+ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_module_efr32xg24_gcc_release.a",
+ "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a",
+ ]
+
+ if (silabs_mcu == "MGM240PB32VNA") {
+ libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb32vna_gcc.a" ]
+ } else if (silabs_mcu == "MGM240PB22VNA") {
+ libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb22vna_gcc.a" ]
+ } else if (silabs_mcu == "MGM240L022RNF") {
+ libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240l022rnf_gcc.a" ]
+ }
+
+ defines += [
+ "MGM24",
+ "EFR32_SERIES2_CONFIG4_MICRO",
+ ]
+ }
+
+ if (use_wf200) {
+ _include_dirs += [
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver",
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus",
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/firmware",
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/pds/brd8022a",
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/secure_link",
+ ]
+ }
+
+ cflags = []
+ foreach(include_dir, _include_dirs) {
+ cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ]
+ }
+
+ cflags += [
+ "-Wno-maybe-uninitialized",
+ "-Wno-shadow",
+ ]
+
+ if (silabs_family == "efr32mg24" || silabs_family == "mgm24") {
+ cflags += [ "-mcmse" ]
+ }
+
+ if (defined(invoker.use_rs911x)) {
+ if (invoker.use_rs911x == true) {
+ #add compilation flags for rs991x build. This will be addressed directly in wiseconnect sdk in the next version release of that sdk
+ cflags += invoker.rs911x_cflags
+ }
+ }
+
+ if (defined(invoker.defines)) {
+ defines += invoker.defines
+ }
+ }
+
+ source_set("efr32_mbedtls_config") {
+ # We're setting the mbedTLS config flags here as the efr32_sdk target
+ # acts as the mbedTLS target for EFR32 builds. We need this for the build
+ # system to recompile mbedTLS (= the SDK) when the mbedTLS config gets
+ # edited.
+ sources = [
+ "${chip_root}/src/platform/silabs/EFR32/efr32-chip-mbedtls-config.h",
+ "${chip_root}/src/platform/silabs/EFR32/efr32-mbedtls-psa-crypto-config.h",
+ ]
+
+ public_deps = [ "${chip_root}/src/crypto:crypto_buildconfig" ]
+ }
+
+ source_set(sdk_target_name) {
+ sources = [
+ "${chip_root}/third_party/mbedtls/repo/include/mbedtls/platform.h",
+ "${efr32_sdk_root}/app/bluetooth/common/in_place_ota_dfu/sl_bt_in_place_ota_dfu.c",
+ "${efr32_sdk_root}/hardware/board/src/sl_board_control_gpio.c",
+ "${efr32_sdk_root}/hardware/board/src/sl_board_init.c",
+ "${efr32_sdk_root}/platform/CMSIS/RTOS2/Source/os_systick.c",
+ "${efr32_sdk_root}/platform/bootloader/api/btl_interface.c",
+ "${efr32_sdk_root}/platform/bootloader/api/btl_interface_storage.c",
+ "${efr32_sdk_root}/platform/bootloader/security/sha/crypto_sha.c",
+ "${efr32_sdk_root}/platform/common/src/sl_slist.c",
+ "${efr32_sdk_root}/platform/driver/button/src/sl_button.c",
+ "${efr32_sdk_root}/platform/driver/button/src/sl_simple_button.c",
+ "${efr32_sdk_root}/platform/emdrv/dmadrv/src/dmadrv.c",
+ "${efr32_sdk_root}/platform/emdrv/gpiointerrupt/src/gpiointerrupt.c",
+ "${efr32_sdk_root}/platform/emdrv/nvm3/src/nvm3_default.c",
+ "${efr32_sdk_root}/platform/emdrv/nvm3/src/nvm3_hal_flash.c",
+ "${efr32_sdk_root}/platform/emdrv/nvm3/src/nvm3_lock.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_adc.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_cmu.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_core.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_crypto.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_emu.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_gpio.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_ldma.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_msc.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_prs.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_rmu.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_rtcc.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_se.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_system.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_timer.c",
+ "${efr32_sdk_root}/platform/peripheral/src/peripheral_sysrtc.c",
+ "${efr32_sdk_root}/platform/radio/rail_lib/hal/efr32/hal_efr.c",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/pa_conversions_efr32.c",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_pti/sl_rail_util_pti.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfrco.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_nvic.c",
+ "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager.c",
+ "${efr32_sdk_root}/platform/service/legacy_hal/src/token_legacy.c",
+ "${efr32_sdk_root}/platform/service/mpu/src/sl_mpu.c",
+ "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager.c",
+ "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager_debug.c",
+ "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager_hal_s0_s1.c",
+ "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager_hal_s2.c",
+ "${efr32_sdk_root}/platform/service/sleeptimer/src/sl_sleeptimer.c",
+ "${efr32_sdk_root}/platform/service/sleeptimer/src/sl_sleeptimer_hal_rtcc.c",
+ "${efr32_sdk_root}/platform/service/sleeptimer/src/sl_sleeptimer_hal_sysrtc.c",
+ "${efr32_sdk_root}/platform/service/system/src/sl_system_init.c",
+ "${efr32_sdk_root}/platform/service/system/src/sl_system_kernel.c",
+ "${efr32_sdk_root}/platform/service/system/src/sl_system_process_action.c",
+ "${efr32_sdk_root}/platform/service/token_manager/src/sl_token_def.c",
+ "${efr32_sdk_root}/platform/service/token_manager/src/sl_token_manager.c",
+ "${efr32_sdk_root}/platform/service/token_manager/src/sl_token_manufacturing.c",
+ "${efr32_sdk_root}/platform/service/udelay/src/sl_udelay.c",
+ "${efr32_sdk_root}/platform/service/udelay/src/sl_udelay_armv6m_gcc.S",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sl_bt_mbedtls_context.c",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sl_bt_rtos_adaptation.c",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sl_bt_stack_init.c",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sli_bt_advertiser_config.c",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sli_bt_connection_config.c",
+ "${efr32_sdk_root}/util/silicon_labs/silabs_core/memory_manager/sl_malloc.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/aes.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/aesni.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/asn1parse.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/asn1write.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/base64.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/bignum.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/camellia.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ccm.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/chacha20.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/chachapoly.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/cipher_wrap.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/cmac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/constant_time.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ctr_drbg.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/debug.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/des.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/dhm.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecdh.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecdsa.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecjpake.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecp.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecp_curves.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/entropy.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/entropy_poll.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/gcm.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/hkdf.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/hmac_drbg.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/md.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/md5.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/oid.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pem.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pk.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pk_wrap.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkcs12.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkcs5.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkparse.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkwrite.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/platform.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/platform_util.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/poly1305.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_client.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_driver_wrappers.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_ecp.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_rsa.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_se.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_slot_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_storage.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_its_file.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ripemd160.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/rsa.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/sha1.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/sha256.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/sha512.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_cache.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_ciphersuites.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_cli.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_cookie.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_msg.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_srv.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_ticket.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_tls.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_tls13_keys.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/threading.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/timing.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/version.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_create.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_crl.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_crt.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_csr.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509write_crt.c",
+ "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509write_csr.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/aes_aes.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/crypto_aes.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/crypto_ecp.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/error.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_ccm.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_cmac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_ecdsa_ecdh.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_sha.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/sl_entropy_hardware.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/sl_mbedtls.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/version_features.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_protocol_crypto_crypto.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_protocol_crypto_radioaes.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/crypto_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sl_psa_its_nvm3.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_trng_driver.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_psa_driver_common.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_psa_driver_init.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_psa_trng.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_builtin_keys.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_signature.c",
+ "${efr32_sdk_root}/util/third_party/freertos/cmsis/Source/cmsis_os2.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/croutine.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/event_groups.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/list.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/queue.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/stream_buffer.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/tasks.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/timers.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/gatt_db.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_bluetooth.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_board_default_init.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_device_init_clocks.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_event_handler.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_simple_button_instances.c",
+ ]
+
+ if (use_system_view) {
+ sources += [
+ "${efr32_sdk_root}/util/third_party/segger/systemview/SEGGER/SEGGER_SYSVIEW.c",
+ "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10/Config/Cortex-M/SEGGER_SYSVIEW_Config_FreeRTOS.c",
+ "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10/SEGGER_SYSVIEW_FreeRTOS.c",
+ ]
+ }
+
+ if (use_wstk_leds) {
+ sources += [
+ "${efr32_sdk_root}/platform/driver/leddrv/src/sl_led.c",
+ "${efr32_sdk_root}/platform/driver/leddrv/src/sl_pwm_led.c",
+ "${efr32_sdk_root}/platform/driver/leddrv/src/sl_simple_led.c",
+ "${efr32_sdk_root}/platform/driver/leddrv/src/sl_simple_rgb_pwm_led.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_simple_led_instances.c",
+ ]
+ }
+
+ # SPI is only used for Wifi
+ if (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) {
+ sources += [
+ "${efr32_sdk_root}/platform/emdrv/spidrv/src/spidrv.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_spidrv_init.c",
+ ]
+ }
+
+ if (defined(invoker.enable_sleepy_device)) {
+ if (invoker.enable_sleepy_device) {
+ sources += [ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/SiliconLabs/tick_power_manager.c" ]
+ }
+ }
+
+ if (defined(enable_fem)) {
+ sources += [
+ "${efr32_sdk_root}/util/plugin/plugin-common/fem-control/fem-control.c",
+ ]
+ }
+
+ # USART sources files
+ if ((defined(invoker.chip_enable_pw_rpc) && invoker.chip_enable_pw_rpc) ||
+ chip_build_libshell || enable_openthread_cli ||
+ (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) ||
+ (defined(invoker.show_qr_code) && invoker.show_qr_code) ||
+ (defined(invoker.disable_lcd) && !invoker.disable_lcd) ||
+ (defined(invoker.use_external_flash) && use_external_flash)) {
+ sources += [
+ "${efr32_sdk_root}/hardware/driver/memlcd/src/memlcd_usart/sl_memlcd_spi.c",
+ "${efr32_sdk_root}/platform/emdrv/uartdrv/src/uartdrv.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_eusart.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_leuart.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_usart.c",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_uartdrv_init.c",
+ ]
+
+ if (defined(invoker.use_external_flash) && use_external_flash) {
+ sources += [ "${efr32_sdk_root}/hardware/driver/mx25_flash_shutdown/src/sl_mx25_flash_shutdown_usart/sl_mx25_flash_shutdown.c" ]
+ }
+ }
+
+ if ((defined(invoker.show_qr_code) && invoker.show_qr_code) ||
+ (defined(invoker.disable_lcd) && !invoker.disable_lcd)) {
+ sources += [
+ "${efr32_sdk_root}/hardware/driver/memlcd/src/sl_memlcd.c",
+ "${efr32_sdk_root}/hardware/driver/memlcd/src/sl_memlcd_display.c",
+ "${efr32_sdk_root}/platform/middleware/glib/dmd/display/dmd_memlcd.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/bmp.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_bitmap.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_circle.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_font_narrow_6x8.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_font_normal_8x8.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_font_number_16x20.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_line.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_polygon.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_rectangle.c",
+ "${efr32_sdk_root}/platform/middleware/glib/glib/glib_string.c",
+ ]
+ }
+
+ if (use_wf200) {
+ sources += [
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus/sl_wfx_bus.c",
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus/sl_wfx_bus_spi.c",
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/secure_link/sl_wfx_secure_link.c",
+ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/sl_wfx.c",
+ ]
+ }
+
+ if (silabs_family == "efr32mg12") {
+ sources += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG12P/Source/startup_efr32mg12p.c",
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG12P/Source/system_efr32mg12p.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dcdc_s1.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s1.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_s1.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s1.c",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sl_apploader_util_s1.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM4F/port.c",
+ ]
+ } else if (silabs_family == "efr32mg21") {
+ sources += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG21/Source/startup_efr32mg21.c",
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG21/Source/system_efr32mg21.c",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_rf_path/sl_rail_util_rf_path.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s2.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfrco.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_s2.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s2.c",
+ "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager_hal_s2.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_entropy.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_handling.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_signature.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_util.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_alt/source/sl_se_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_aes.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_gcm.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_jpake.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_radioaes_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/port.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c",
+ ]
+ } else if (silabs_family == "efr32mg24") {
+ sources += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG24/Source/startup_efr32mg24.c",
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG24/Source/system_efr32mg24.c",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/pa_curves_efr32.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dcdc_s2.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s2.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_s2.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s2.c",
+ "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager_hal_s2.c",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sl_apploader_util_s2.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_attestation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_entropy.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_handling.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_signature.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_util.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_aes.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_jpake.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_radioaes_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/port.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c",
+ ]
+ } else if (silabs_family == "mgm24") {
+ sources += [
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Source/startup_mgm24.c",
+ "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Source/system_mgm24.c",
+ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/pa_curves_efr32.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dcdc_s2.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s2.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_mgm24.c",
+ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s2.c",
+ "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager_hal_s2.c",
+ "${efr32_sdk_root}/protocol/bluetooth/src/sl_apploader_util_s2.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_attestation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_entropy.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_handling.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_signature.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_util.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_aes.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_jpake.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_radioaes_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_management.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_aead.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_cipher.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_hash.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_mac.c",
+ "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_key_derivation.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/port.c",
+ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c",
+ ]
+ }
+
+ if (silabs_board == "BRD4186A" || silabs_board == "BRD4186C" ||
+ silabs_board == "BRD4187A" || silabs_board == "BRD4187C") {
+ sources += [ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dpll_s2.c" ]
+ }
+
+ public_deps = [
+ ":efr32_mbedtls_config",
+ "${segger_rtt_root}:segger_rtt",
+ "${segger_rtt_root}:segger_rtt_printf",
+ "${segger_rtt_root}:segger_rtt_syscalls",
+ ]
+
+ if (defined(invoker.sources)) {
+ sources += invoker.sources
+ }
+
+ public_configs = [ ":${sdk_target_name}_config" ]
+ }
+}