diff --git a/examples/lighting-app/silabs/SiWx917/.gn b/examples/lighting-app/silabs/SiWx917/.gn
new file mode 100644
index 00000000000000..4c078f6acefdcc
--- /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 00000000000000..3a812b966d3361
--- /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 00000000000000..ae7565f492c620
--- /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.
+
+
+
+- [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)
+
+
+
+> **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)
+
+
+
+## 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.
+
+
+
+## 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
+
+
+
+## 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.
+
+
+
+## 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
+
+
+
+## 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.
+
+ [SVR] Copy/paste the below URL in a browser to see the QR Code:
+ [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: 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 2002::2/64`
+
+ - On PC(Linux): `sudo ip addr add dev 2002::1/64`
+
+ - Add Ipv6 route on PC(Linux)
+ `sudo ip route add /64 via 2002::2`
+
+
+
+## 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. -b 115200 -o //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 00000000000000..d216faa0a07dae
--- /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 00000000000000..363d2be9e6f362
--- /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 00000000000000..d391814190d09f
--- /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 00000000000000..995884e6163eb5
--- /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 00000000000000..ffadaf9706cd2e
--- /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 00000000000000..7a19b719edad25
--- /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 00000000000000..df80995592fd95
--- /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
+#include
+
+#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
+#include
+#include
+#include
+
+/**********************************************************
+ * 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 00000000000000..4b3d8f571c9057
--- /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 00000000000000..6d286faa30ef96
--- /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
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+
+#include
+
+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 00000000000000..850649df25e27d
--- /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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+#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(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(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(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(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 00000000000000..31a4ca0ba91e7c
--- /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
+
+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(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(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(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(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(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 00000000000000..cfbcbc8a191411
--- /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
+#include
+#include
+#include
+
+using namespace ::chip;
+using namespace ::chip::app::Clusters;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+ uint8_t * value)
+{
+ 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 00000000000000..2594f6f9216e78
--- /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
+
+#include "AppConfig.h"
+#include "init_efrPlatform.h"
+#include "sl_simple_button_instances.h"
+#include "sl_system_kernel.h"
+#include
+#include
+#include
+#include
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+#include
+#else
+#include
+#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 00000000000000..59307833b4fee9
--- /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 00000000000000..40a8bb79d84b6a
--- /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 00000000000000..dbd8473a6c89de
--- /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 00000000000000..85748b35359d3f
--- /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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if CHIP_ENABLE_OPENTHREAD
+#include
+#include
+#include
+#endif // CHIP_ENABLE_OPENTHREAD
+
+#ifdef SL_WIFI
+#include "wfx_host_events.h"
+#include
+#include
+#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 00000000000000..febd7aa68591b2
--- /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
+#include
+
+#include "AppEvent.h"
+#include "FreeRTOS.h"
+#include "sl_simple_button_instances.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+#include
+#include
+#include
+
+#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 00000000000000..6e097ffa4db0e2
--- /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
+#include
+#include
+#include
+#include
+
+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(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(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(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(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(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(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(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(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(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 00000000000000..99d90496b30d12
--- /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
+#include
+
+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
+{
+public:
+ EFR32DeviceDataProvider() :
+ CommissionableDataProvider(), Internal::GenericDeviceInstanceInfoProvider(
+ 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 00000000000000..50f4c24ff31679
--- /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
+
+#include
+
+#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 00000000000000..10ffcac363520d
--- /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
+
+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 00000000000000..d779cb9d3ef4b6
--- /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
+
+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 00000000000000..9da075e4e79d42
--- /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
+
+#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 00000000000000..1056cf5a3533b4
--- /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
+
+#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 00000000000000..a4f8ac4369e175
--- /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
+#include
+#include
+#include
+#include
+
+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 00000000000000..69ba106fd69872
--- /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(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 00000000000000..116287e9a37155
--- /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
+
+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 00000000000000..1726b62a75d86b
--- /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 = ""
+chip_device_project_config_include = ""
+chip_project_config_include = ""
+chip_inet_project_config_include = ""
+chip_system_project_config_include = ""
diff --git a/examples/platform/silabs/SiWx917/board_config.h b/examples/platform/silabs/SiWx917/board_config.h
new file mode 100644
index 00000000000000..8c495b4fa7f513
--- /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 00000000000000..4eca9c0c48e7aa
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui-bitmaps.h
@@ -0,0 +1,356 @@
+/***************************************************************************/ /**
+ * @file
+ * @brief User Interface bitmaps for demo.
+ *******************************************************************************
+ * # License
+ * Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com
+ *******************************************************************************
+ *
+ * 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 00000000000000..73a8d52ea71090
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui.c
@@ -0,0 +1,136 @@
+/**
+ * @file
+ * @brief User Interface core logic for demo.
+ *******************************************************************************
+ * # License
+ * Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com
+ *******************************************************************************
+ *
+ * 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
+#include
+
+// 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 00000000000000..6197a4e73c71ef
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui.h
@@ -0,0 +1,139 @@
+/***************************************************************************/ /**
+ * @file
+ * @brief User Interface for demo.
+ *******************************************************************************
+ * # License
+ * Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com
+ *******************************************************************************
+ *
+ * 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 00000000000000..6e1f2d2fe93de3
--- /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
+#include
+
+#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 00000000000000..d375b7a133c9aa
--- /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
+#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 00000000000000..bd2bf771c60152
--- /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
+
+void appError(int err)
+{
+ SILABS_LOG("!!!!!!!!!!!! App Critical Error: %d !!!!!!!!!!!", err);
+ portDISABLE_INTERRUPTS();
+ while (true)
+ ;
+}
+
+void appError(CHIP_ERROR error)
+{
+ appError(static_cast(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 00000000000000..b0d508de5f8fe8
--- /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
+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 00000000000000..993b4fefe069f8
--- /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
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include
+#include
+
+#include
+
+#if CHIP_ENABLE_OPENTHREAD
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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 00000000000000..aeb47b8aaed3d1
--- /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 00000000000000..f9f4f55f8b9a73
--- /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
+ * Copyright 2022 Silicon Laboratories Inc. www.silabs.com
+ *******************************************************************************
+ *
+ * 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 00000000000000..2c9de0ddede7d7
--- /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
+ * Copyright 2018 Silicon Laboratories Inc. www.silabs.com
+ *******************************************************************************
+ *
+ * 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 00000000000000..b057a9af720a7a
--- /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
+ * Copyright 2022 Silicon Laboratories, Inc. www.silabs.com
+ *******************************************************************************
+ *
+ * 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 00000000000000..b057a9af720a7a
--- /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
+ * Copyright 2022 Silicon Laboratories, Inc. www.silabs.com
+ *******************************************************************************
+ *
+ * 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 00000000000000..83e909588d9811
--- /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
+
+#include
+
+#include
+
+#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
+// If building with the EFR32-provided crypto backend, we can use the
+// opaque keystore
+#if CHIP_CRYPTO_PLATFORM
+#include
+static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeystore;
+#endif
+
+#include "EFR32DeviceDataProvider.h"
+
+#if CHIP_ENABLE_OPENTHREAD
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// ================================================================================
+// 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(&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(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 00000000000000..e0af60356becf9
--- /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
+#include
+#include
+#include
+
+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 00000000000000..dccf3c816b7b66
--- /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
+
+// 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 00000000000000..722d2a7cad24e6
--- /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 00000000000000..f11f5e928f3e14
--- /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 00000000000000..4bc7d98f7477c4
--- /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
+#include
+#include
+#include
+
+#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(dest));
+ return ret < 0 ? Status::FailedPrecondition() : OkStatus();
+}
+
+Status WriteByte(std::byte b)
+{
+ int16_t ret = console_putchar(reinterpret_cast(&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 00000000000000..f01cac3b657c7c
--- /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
+#include
+#include
+
+#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 00000000000000..204e7519d29b5b
--- /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 00000000000000..4e195433edc57f
--- /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 00000000000000..40e4189635d71c
--- /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
+#include
+#include
+
+#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 00000000000000..1ff5bc5fedf4f2
--- /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
+#include
+#include
+
+#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 00000000000000..f57d47a4439bc5
--- /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
+#include
+
+#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 00000000000000..c6d6381932d3ea
--- /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 00000000000000..f11981023e35f2
--- /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 00000000000000..7d3be406fbce2f
--- /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
+#include
+#include
+
+#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 00000000000000..f2a47b5cb8d2b5
--- /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 00000000000000..380fc8f29e1693
--- /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 00000000000000..a55e0aeb5cab2e
--- /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
+#include
+#include
+
+#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 00000000000000..8d8a3c1803382b
--- /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
+#include
+#include
+
+#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 00000000000000..76dbca22ce52d5
--- /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
+#include
+
+#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 00000000000000..f708030223b2f7
--- /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
+
+#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 00000000000000..fb35093797679d
--- /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
+#include
+#include
+
+#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 00000000000000..26bd7886654700
--- /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
+#include
+#include
+
+#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
+
+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(static_cast(sl_wfx_context->state) | static_cast(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(static_cast(sl_wfx_context->state) & ~static_cast(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(static_cast(sl_wfx_context->state) & ~static_cast(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(static_cast(sl_wfx_context->state) | static_cast(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(static_cast(sl_wfx_context->state) & ~static_cast(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(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(sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK);
+ break;
+ case WFX_SEC_WPA_WPA2_MIXED:
+ wifi_provision.security = static_cast(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(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 00000000000000..96ab9681745fdc
--- /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 00000000000000..deb468d1a6af73
--- /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)
+
+// 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 00000000000000..ddad3ec5b95dde
--- /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
+
+#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 00000000000000..dc9bcd28524623
--- /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 00000000000000..28ffdda2c3852f
--- /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
+#include
+#include
+
+// 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 00000000000000..8a00e454ade504
--- /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
+#include
+#include
+
+#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 00000000000000..6838b9bac14eb4
--- /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
+
+#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 00000000000000..358384a81121bf
--- /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 00000000000000..12973d3c8ffb67
--- /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
+#include
+#include
+#include
+
+/* 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 00000000000000..a76f26c6df6b20
--- /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
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include "sl_component_catalog.h"
+
+#include
+
+#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
+#include
+#include
+#include
+#include
+#include
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+#include
+#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(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(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(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;
+ 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 00000000000000..b67c63c486a719
--- /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 00000000000000..13af1ae5a557b6
--- /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
+
+#include
+
+// Include version header to get configuration information
+#include
+
+#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
+#include
+
+// Includes needed for certificate parsing
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#include
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+#include
+#include
+#include
+
+#if defined(MBEDTLS_ERROR_C)
+#include
+#endif // defined(MBEDTLS_ERROR_C)
+
+#include
+#include
+#include
+#include