From f7d6218b753d4a95a8316b8695e34134da7c1144 Mon Sep 17 00:00:00 2001 From: weicheng Date: Tue, 16 May 2023 22:43:10 +0800 Subject: [PATCH] [ASR] add ASR582X & ASR595X support (#26361) * [ASR] add ASR582X & ASR595X support * Restyled * update wordlist * update asr sdk commit id * remove getenv from gni, use --args;remove asr build example script;remove DOGO wordlist;add asr submodule platforms;update copyright time to 2023 * rename ASRUtils to matter_shell to implement shell function; remove ble and ota config * update build_examples.py build support,update README --------- Co-authored-by: weicheng --- .github/.wordlist.txt | 1 + .gitmodules | 10 + build_overrides/asr.gni | 23 + config/asr/toolchain/BUILD.gn | 47 ++ examples/build_overrides/asr.gni | 23 + examples/lighting-app/asr/.gn | 29 + examples/lighting-app/asr/BUILD.gn | 128 ++++ examples/lighting-app/asr/README.md | 98 +++ examples/lighting-app/asr/args.gni | 27 + examples/lighting-app/asr/build_overrides | 1 + examples/lighting-app/asr/cfg.gni | 23 + examples/lighting-app/asr/include/AppConfig.h | 48 ++ examples/lighting-app/asr/include/AppTask.h | 44 ++ .../asr/include/CHIPProjectConfig.h | 112 +++ .../asr/include/DeviceCallbacks.h | 47 ++ examples/lighting-app/asr/src/AppTask.cpp | 168 +++++ .../lighting-app/asr/src/DeviceCallbacks.cpp | 248 +++++++ examples/lighting-app/asr/src/main.cpp | 93 +++ .../asr/third_party/connectedhomeip | 1 + examples/platform/asr/BUILD.gn | 22 + examples/platform/asr/CHIPDeviceManager.cpp | 76 ++ examples/platform/asr/CHIPDeviceManager.h | 124 ++++ examples/platform/asr/LEDWidget.cpp | 280 ++++++++ examples/platform/asr/LEDWidget.h | 80 +++ examples/platform/asr/args.gni | 21 + examples/platform/asr/init_Matter.cpp | 121 ++++ examples/platform/asr/init_Matter.h | 30 + examples/platform/asr/init_OTARequestor.cpp | 84 +++ examples/platform/asr/init_OTARequestor.h | 30 + examples/platform/asr/init_asrPlatform.cpp | 163 +++++ examples/platform/asr/init_asrPlatform.h | 26 + examples/platform/asr/shell/launch_shell.cpp | 42 ++ examples/platform/asr/shell/launch_shell.h | 24 + examples/platform/asr/shell/matter_shell.cpp | 142 ++++ examples/platform/asr/shell/matter_shell.h | 52 ++ scripts/build/BUILD.gn | 1 + scripts/build/build/targets.py | 24 + scripts/build/builders/asr.py | 122 ++++ .../build/testdata/all_targets_linux_x64.txt | 1 + scripts/checkout_submodules.py | 1 + scripts/tools/check_includes_config.py | 1 + src/lib/shell/BUILD.gn | 5 + src/lib/shell/streamer_asr.cpp | 95 +++ src/lwip/BUILD.gn | 15 +- src/platform/ASR/ASRConfig.cpp | 300 ++++++++ src/platform/ASR/ASRConfig.h | 159 +++++ src/platform/ASR/ASRFactoryDataProvider.cpp | 481 +++++++++++++ src/platform/ASR/ASRFactoryDataProvider.h | 95 +++ src/platform/ASR/ASROTAImageProcessor.cpp | 271 +++++++ src/platform/ASR/ASROTAImageProcessor.h | 72 ++ src/platform/ASR/ASRUtils.cpp | 305 ++++++++ src/platform/ASR/ASRUtils.h | 84 +++ src/platform/ASR/BLEAppSvc.cpp | 203 ++++++ src/platform/ASR/BLEAppSvc.h | 94 +++ src/platform/ASR/BLEManagerImpl.cpp | 662 ++++++++++++++++++ src/platform/ASR/BLEManagerImpl.h | 165 +++++ src/platform/ASR/BUILD.gn | 89 +++ src/platform/ASR/BlePlatformConfig.h | 33 + src/platform/ASR/CHIPDevicePlatformConfig.h | 42 ++ src/platform/ASR/CHIPDevicePlatformEvent.h | 38 + src/platform/ASR/CHIPPlatformConfig.h | 65 ++ src/platform/ASR/ConfigurationManagerImpl.cpp | 233 ++++++ src/platform/ASR/ConfigurationManagerImpl.h | 83 +++ src/platform/ASR/ConnectivityManagerImpl.cpp | 646 +++++++++++++++++ src/platform/ASR/ConnectivityManagerImpl.h | 207 ++++++ .../ASR/DiagnosticDataProviderImpl.cpp | 351 ++++++++++ src/platform/ASR/DiagnosticDataProviderImpl.h | 89 +++ src/platform/ASR/InetPlatformConfig.h | 36 + src/platform/ASR/KeyValueStoreManagerImpl.cpp | 119 ++++ src/platform/ASR/KeyValueStoreManagerImpl.h | 73 ++ src/platform/ASR/Logging.cpp | 90 +++ src/platform/ASR/LwIPCoreLock.cpp | 62 ++ src/platform/ASR/NetworkCommissioningDriver.h | 153 ++++ .../ASR/NetworkCommissioningWiFiDriver.cpp | 352 ++++++++++ src/platform/ASR/PlatformManagerImpl.cpp | 353 ++++++++++ src/platform/ASR/PlatformManagerImpl.h | 129 ++++ src/platform/ASR/SystemPlatformConfig.h | 42 ++ src/platform/ASR/SystemTimeSupport.cpp | 88 +++ src/platform/ASR/SystemTimeSupport.h | 28 + src/platform/ASR/WarmPlatformConfig.h | 31 + src/platform/ASR/args.gni | 27 + src/platform/ASR/route_hook/asr_route_hook.c | 209 ++++++ src/platform/ASR/route_hook/asr_route_hook.h | 10 + src/platform/ASR/route_hook/asr_route_table.c | 174 +++++ src/platform/ASR/route_hook/asr_route_table.h | 76 ++ src/platform/BUILD.gn | 7 + src/platform/device.gni | 7 +- third_party/asr/asr582x/BUILD.gn | 184 +++++ third_party/asr/asr582x/asr_sdk | 1 + third_party/asr/asr582x/asr_sdk.gni | 264 +++++++ third_party/asr/asr595x/BUILD.gn | 203 ++++++ third_party/asr/asr595x/asr_sdk | 1 + third_party/asr/asr595x/asr_sdk.gni | 278 ++++++++ third_party/asr/asr_arm.gni | 19 + third_party/asr/asr_executable.gni | 42 ++ third_party/asr/asr_riscv.gni | 16 + 96 files changed, 10591 insertions(+), 3 deletions(-) create mode 100755 build_overrides/asr.gni create mode 100755 config/asr/toolchain/BUILD.gn create mode 100644 examples/build_overrides/asr.gni create mode 100755 examples/lighting-app/asr/.gn create mode 100755 examples/lighting-app/asr/BUILD.gn create mode 100755 examples/lighting-app/asr/README.md create mode 100755 examples/lighting-app/asr/args.gni create mode 120000 examples/lighting-app/asr/build_overrides create mode 100755 examples/lighting-app/asr/cfg.gni create mode 100644 examples/lighting-app/asr/include/AppConfig.h create mode 100644 examples/lighting-app/asr/include/AppTask.h create mode 100755 examples/lighting-app/asr/include/CHIPProjectConfig.h create mode 100644 examples/lighting-app/asr/include/DeviceCallbacks.h create mode 100644 examples/lighting-app/asr/src/AppTask.cpp create mode 100644 examples/lighting-app/asr/src/DeviceCallbacks.cpp create mode 100644 examples/lighting-app/asr/src/main.cpp create mode 120000 examples/lighting-app/asr/third_party/connectedhomeip create mode 100755 examples/platform/asr/BUILD.gn create mode 100644 examples/platform/asr/CHIPDeviceManager.cpp create mode 100644 examples/platform/asr/CHIPDeviceManager.h create mode 100644 examples/platform/asr/LEDWidget.cpp create mode 100644 examples/platform/asr/LEDWidget.h create mode 100755 examples/platform/asr/args.gni create mode 100644 examples/platform/asr/init_Matter.cpp create mode 100644 examples/platform/asr/init_Matter.h create mode 100644 examples/platform/asr/init_OTARequestor.cpp create mode 100755 examples/platform/asr/init_OTARequestor.h create mode 100644 examples/platform/asr/init_asrPlatform.cpp create mode 100755 examples/platform/asr/init_asrPlatform.h create mode 100644 examples/platform/asr/shell/launch_shell.cpp create mode 100755 examples/platform/asr/shell/launch_shell.h create mode 100644 examples/platform/asr/shell/matter_shell.cpp create mode 100644 examples/platform/asr/shell/matter_shell.h create mode 100644 scripts/build/builders/asr.py create mode 100644 src/lib/shell/streamer_asr.cpp create mode 100644 src/platform/ASR/ASRConfig.cpp create mode 100644 src/platform/ASR/ASRConfig.h create mode 100644 src/platform/ASR/ASRFactoryDataProvider.cpp create mode 100644 src/platform/ASR/ASRFactoryDataProvider.h create mode 100644 src/platform/ASR/ASROTAImageProcessor.cpp create mode 100755 src/platform/ASR/ASROTAImageProcessor.h create mode 100644 src/platform/ASR/ASRUtils.cpp create mode 100644 src/platform/ASR/ASRUtils.h create mode 100644 src/platform/ASR/BLEAppSvc.cpp create mode 100644 src/platform/ASR/BLEAppSvc.h create mode 100644 src/platform/ASR/BLEManagerImpl.cpp create mode 100644 src/platform/ASR/BLEManagerImpl.h create mode 100755 src/platform/ASR/BUILD.gn create mode 100755 src/platform/ASR/BlePlatformConfig.h create mode 100644 src/platform/ASR/CHIPDevicePlatformConfig.h create mode 100755 src/platform/ASR/CHIPDevicePlatformEvent.h create mode 100755 src/platform/ASR/CHIPPlatformConfig.h create mode 100644 src/platform/ASR/ConfigurationManagerImpl.cpp create mode 100755 src/platform/ASR/ConfigurationManagerImpl.h create mode 100644 src/platform/ASR/ConnectivityManagerImpl.cpp create mode 100644 src/platform/ASR/ConnectivityManagerImpl.h create mode 100644 src/platform/ASR/DiagnosticDataProviderImpl.cpp create mode 100644 src/platform/ASR/DiagnosticDataProviderImpl.h create mode 100755 src/platform/ASR/InetPlatformConfig.h create mode 100644 src/platform/ASR/KeyValueStoreManagerImpl.cpp create mode 100755 src/platform/ASR/KeyValueStoreManagerImpl.h create mode 100644 src/platform/ASR/Logging.cpp create mode 100644 src/platform/ASR/LwIPCoreLock.cpp create mode 100644 src/platform/ASR/NetworkCommissioningDriver.h create mode 100644 src/platform/ASR/NetworkCommissioningWiFiDriver.cpp create mode 100644 src/platform/ASR/PlatformManagerImpl.cpp create mode 100644 src/platform/ASR/PlatformManagerImpl.h create mode 100755 src/platform/ASR/SystemPlatformConfig.h create mode 100644 src/platform/ASR/SystemTimeSupport.cpp create mode 100755 src/platform/ASR/SystemTimeSupport.h create mode 100755 src/platform/ASR/WarmPlatformConfig.h create mode 100755 src/platform/ASR/args.gni create mode 100644 src/platform/ASR/route_hook/asr_route_hook.c create mode 100755 src/platform/ASR/route_hook/asr_route_hook.h create mode 100755 src/platform/ASR/route_hook/asr_route_table.c create mode 100755 src/platform/ASR/route_hook/asr_route_table.h mode change 100755 => 100644 src/platform/device.gni create mode 100755 third_party/asr/asr582x/BUILD.gn create mode 160000 third_party/asr/asr582x/asr_sdk create mode 100755 third_party/asr/asr582x/asr_sdk.gni create mode 100755 third_party/asr/asr595x/BUILD.gn create mode 160000 third_party/asr/asr595x/asr_sdk create mode 100755 third_party/asr/asr595x/asr_sdk.gni create mode 100644 third_party/asr/asr_arm.gni create mode 100644 third_party/asr/asr_executable.gni create mode 100644 third_party/asr/asr_riscv.gni diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index d77e05b4f26c58..251fa2fee90749 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -88,6 +88,7 @@ armv ASAN asdk AssertionError +ASR AST ASYNC atomics diff --git a/.gitmodules b/.gitmodules index 0f5d8dfa6e39e5..5478beda037473 100644 --- a/.gitmodules +++ b/.gitmodules @@ -298,3 +298,13 @@ path = third_party/imgui/repo url = https://github.com/ocornut/imgui platforms = linux +[submodule "third_party/asr/asr582x/asr_sdk"] + path = third_party/asr/asr582x/asr_sdk + url = https://github.com/asriot/ASR582X_Freertos.git + branch = matter + platforms = asr +[submodule "third_party/asr/asr595x/asr_sdk"] + path = third_party/asr/asr595x/asr_sdk + url = https://github.com/asriot/ASR595X_Freertos.git + branch = matter + platforms = asr diff --git a/build_overrides/asr.gni b/build_overrides/asr.gni new file mode 100755 index 00000000000000..d012a516b2102f --- /dev/null +++ b/build_overrides/asr.gni @@ -0,0 +1,23 @@ +# Copyright (c) 2023 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. + +declare_args() { + asr_ic_family = "asr582x" + + # Root directory for ASR SDK build files. + asr_sdk_build_root = "//third_party/connectedhomeip/third_party/asr/asr582x" + + # Root directory for ASR toolchain. + asr_toolchain_root = "" +} diff --git a/config/asr/toolchain/BUILD.gn b/config/asr/toolchain/BUILD.gn new file mode 100755 index 00000000000000..d13d7e1888f07a --- /dev/null +++ b/config/asr/toolchain/BUILD.gn @@ -0,0 +1,47 @@ +# Copyright (c) 2023 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/asr.gni") +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +assert(asr_ic_family == "asr582x" || asr_ic_family == "asr595x", + "Unsupported ASR IC: ${asr_ic_family}") + +if (asr_ic_family == "asr582x") { + import("${build_root}/toolchain/arm_gcc/arm_toolchain.gni") + _tool_name_root = "${asr_toolchain_root}arm-none-eabi-" +} + +if (asr_ic_family == "asr595x") { + import("${build_root}/toolchain/riscv_gcc/riscv_toolchain.gni") + _tool_name_root = "${asr_toolchain_root}riscv-asr-elf-" +} + +declare_args() { + asr_ar = _tool_name_root + "ar" + asr_cc = _tool_name_root + "gcc" + asr_cxx = _tool_name_root + "g++" +} + +gcc_toolchain("asrtoolchain") { + ar = asr_ar + cc = asr_cc + cxx = asr_cxx + + toolchain_args = { + current_os = "freertos" + is_clang = false + } +} diff --git a/examples/build_overrides/asr.gni b/examples/build_overrides/asr.gni new file mode 100644 index 00000000000000..d012a516b2102f --- /dev/null +++ b/examples/build_overrides/asr.gni @@ -0,0 +1,23 @@ +# Copyright (c) 2023 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. + +declare_args() { + asr_ic_family = "asr582x" + + # Root directory for ASR SDK build files. + asr_sdk_build_root = "//third_party/connectedhomeip/third_party/asr/asr582x" + + # Root directory for ASR toolchain. + asr_toolchain_root = "" +} diff --git a/examples/lighting-app/asr/.gn b/examples/lighting-app/asr/.gn new file mode 100755 index 00000000000000..8d75f1eafcdb89 --- /dev/null +++ b/examples/lighting-app/asr/.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2023 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" + + import("//args.gni") +} diff --git a/examples/lighting-app/asr/BUILD.gn b/examples/lighting-app/asr/BUILD.gn new file mode 100755 index 00000000000000..55b102fb25116f --- /dev/null +++ b/examples/lighting-app/asr/BUILD.gn @@ -0,0 +1,128 @@ +# Copyright (c) 2023 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/asr.gni") +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") +import("${asr_sdk_build_root}/asr_sdk.gni") +import("${build_root}/config/defaults.gni") +import("${chip_root}/src/lib/lib.gni") +import("${chip_root}/src/platform/device.gni") +import("${chip_root}/third_party/asr/asr_executable.gni") + +import("cfg.gni") + +assert(current_os == "freertos") + +asr_project_dir = "${chip_root}/examples/lighting-app/asr" +examples_plat_dir = "${chip_root}/examples/platform/asr" + +declare_args() { + # Dump memory usage at link time. + chip_print_memory_usage = false +} + +asr_sdk_sources("lighting_app_sdk_sources") { + include_dirs = [ + "${chip_root}/src/platform/ASR", + "${asr_project_dir}/include", + "${examples_plat_dir}", + ] + + defines = [ + "ASR_LOG_ENABLED=1", + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setupDiscriminator}", + ] + + if (chip_enable_factory_data) { + defines += [ + "CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER=1", + "CONFIG_ENABLE_ASR_FACTORY_DEVICE_INFO_PROVIDER=1", + ] + } + + if (chip_lwip_ip6_hook) { + defines += [ + "CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT", + "CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT", + ] + } + + sources = [ "${asr_project_dir}/include/CHIPProjectConfig.h" ] + + public_configs = [ "${asr_sdk_build_root}:asr_sdk_config" ] +} + +asr_executable("lighting_app") { + include_dirs = [] + defines = [] + output_name = "chip-asr-lighting-example.out" + + sources = [ + "${examples_plat_dir}/CHIPDeviceManager.cpp", + "${examples_plat_dir}/LEDWidget.cpp", + "${examples_plat_dir}/init_Matter.cpp", + "${examples_plat_dir}/init_asrPlatform.cpp", + "${examples_plat_dir}/shell/matter_shell.cpp", + "src/AppTask.cpp", + "src/DeviceCallbacks.cpp", + "src/main.cpp", + ] + + if (chip_enable_ota_requestor) { + sources += [ "${examples_plat_dir}/init_OTARequestor.cpp" ] + } + + deps = [ + ":lighting_app_sdk_sources", + "${chip_root}/examples/common/QRCode", + "${chip_root}/examples/lighting-app/lighting-common", + "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/lib", + "${chip_root}/src/setup_payload", + ] + + include_dirs += [ + "include", + "${examples_plat_dir}", + "${asr_project_dir}/include", + "${chip_root}/src/lib", + ] + + defines = [ "ASR_NETWORK_LAYER_BLE=${chip_config_network_layer_ble}" ] + + if (chip_build_libshell) { + defines += [ "CONFIG_ENABLE_CHIP_SHELL=1" ] + sources += [ "${examples_plat_dir}/shell/launch_shell.cpp" ] + include_dirs += [ "${examples_plat_dir}/shell" ] + } + + if (chip_print_memory_usage) { + ldflags += [ + "-Wl,--print-memory-usage", + "-fstack-usage", + ] + } + + output_dir = root_out_dir +} + +group("asr") { + deps = [ ":lighting_app" ] +} + +group("default") { + deps = [ ":asr" ] +} diff --git a/examples/lighting-app/asr/README.md b/examples/lighting-app/asr/README.md new file mode 100755 index 00000000000000..78755f02f9119a --- /dev/null +++ b/examples/lighting-app/asr/README.md @@ -0,0 +1,98 @@ +# CHIP ASR Lighting Example + +This example demonstrates the Matter Lighting application on ASR platform. + +--- + +- [CHIP ASR Lighting Example](#chip-asr-lighting-example) + - [Supported Chips](#supported-chips) + - [Building the Example Application](#building-the-example-application) + - [Commissioning](#commissioning) + - [BLE mode](#ble-mode) + - [IP mode](#ip-mode) + - [Cluster Control](#cluster-control) + +--- + +## Supported Chips + +The CHIP demo application is supported on: + +- ASR582X +- ASR595X + +## Building the Example Application + +- [Setup CHIP Environment](../../../docs/guides/BUILDING.md) + +- Setup toolchain for ASR582X,download gcc-arm-none-eabi-9-2019-q4-major,then + export `ASR_TOOLCHAIN_PATH`: + ``` + export ASR_TOOLCHAIN_PATH={path-to-toolchain}/gcc-arm-none-eabi-9-2019-q4-major/bin/ + ``` + for ASR595X,download asr_riscv_gnu_toolchain_10.2_ubuntu,then export + `ASR_TOOLCHAIN_PATH`: + ``` + export ASR_TOOLCHAIN_PATH={path-to-toolchain}/asr_riscv_gnu_toolchain_10.2_ubuntu-16.04/bin/ + ``` +- Setup Chip environment + - for ASR582X: + ``` + export ASR_BOARD=asr582x + ``` + - for ASR595X: + ``` + export ASR_BOARD=asr595x + ``` +- Building the Application + ``` + ./scripts/build/build_examples.py --target asr-$ASR_BOARD-lighting build + ``` +- The output image files are stored in the subdirectories under `out`, the + subdirectory name is the same as the argument specified after the option + `--target` when build the examples. + +- After building the application, `DOGO` tool is used to flash it to the + board. + +## Commissioning + +There are two commissioning modes supported by ASR platform: + +### BLE mode + +1. Build and Flash +2. The example will run automatically after booting the ASR board. +3. Restore factory settings using command `recovery` +4. Commissioning with + [Chip-Tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool) + +### IP mode + +1. Build and Flash +2. The example will run automatically after booting the ASR board. +3. Restore factory settings using command `recovery` +4. Connect to AP using command `wifi_open sta [ssid] [password]` +5. Commissioning with + [Chip-Tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool) + +## Cluster Control + +After successful commissioning, use `chip-tool` to control the board + +- OnOff Cluster + ``` + ./chip-tool onoff on 1 + ./chip-tool onoff off 1 + ./chip-tool onoff toggle 1 + ``` +- LevelControl Cluster + + ``` + ./chip-tool levelcontrol move-to-level 128 10 0 0 1 + ``` + +- ColorControl Cluster + ``` + ./chip-tool colorcontrol move-to-hue-and-saturation 240 100 0 0 0 1 + ``` diff --git a/examples/lighting-app/asr/args.gni b/examples/lighting-app/asr/args.gni new file mode 100755 index 00000000000000..aa2f74634e4d1b --- /dev/null +++ b/examples/lighting-app/asr/args.gni @@ -0,0 +1,27 @@ +# Copyright (c) 2023 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("//cfg.gni") +import("${chip_root}/src/platform/ASR/args.gni") + +asr_target_project = + get_label_info(":lighting_app_sdk_sources", "label_no_toolchain") + +declare_args() { + # Disable lock tracking, since our FreeRTOS configuration does not set + # INCLUDE_xSemaphoreGetMutexHolder + chip_stack_lock_tracking = "none" +} diff --git a/examples/lighting-app/asr/build_overrides b/examples/lighting-app/asr/build_overrides new file mode 120000 index 00000000000000..194ee0b812dc3d --- /dev/null +++ b/examples/lighting-app/asr/build_overrides @@ -0,0 +1 @@ +../../build_overrides/ \ No newline at end of file diff --git a/examples/lighting-app/asr/cfg.gni b/examples/lighting-app/asr/cfg.gni new file mode 100755 index 00000000000000..15fe50e79efb6d --- /dev/null +++ b/examples/lighting-app/asr/cfg.gni @@ -0,0 +1,23 @@ +# Copyright (c) 2023 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. + +declare_args() { + chip_enable_factory_data = false + + chip_lwip_ip6_hook = false + + setupPinCode = 20202021 + + setupDiscriminator = 3840 +} diff --git a/examples/lighting-app/asr/include/AppConfig.h b/examples/lighting-app/asr/include/AppConfig.h new file mode 100644 index 00000000000000..fd0622e3dae21e --- /dev/null +++ b/examples/lighting-app/asr/include/AppConfig.h @@ -0,0 +1,48 @@ +/* + * + * Copyright (c) 2021 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 + +// ---- Lighting Example App Config ---- + +#if (CFG_EASY_LOG_ENABLE == 1) +#include "elog.h" +#endif + +#define APP_TASK_NAME "APP" + +#define LIGHT_LED PWM_OUTPUT_CH4 + +#define APP_TASK_STACK_SIZE (1024 * 4) + +#define MATTER_DEVICE_NAME "ASR-Lighting" + +#ifdef __cplusplus +extern "C" { +#endif + +void appError(int err); +void ASR_LOG(const char * aFormat, ...); + +#ifdef __cplusplus +} + +#include +void appError(CHIP_ERROR error); +#endif diff --git a/examples/lighting-app/asr/include/AppTask.h b/examples/lighting-app/asr/include/AppTask.h new file mode 100644 index 00000000000000..de31a9cee6db47 --- /dev/null +++ b/examples/lighting-app/asr/include/AppTask.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2021 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 +#include + +#include +#include + +class AppTask +{ + +public: + CHIP_ERROR StartAppTask(); + static void AppTaskMain(void * pvParameter); + +private: + friend AppTask & GetAppTask(void); + + static AppTask sAppTask; +}; + +inline AppTask & GetAppTask(void) +{ + return AppTask::sAppTask; +} diff --git a/examples/lighting-app/asr/include/CHIPProjectConfig.h b/examples/lighting-app/asr/include/CHIPProjectConfig.h new file mode 100755 index 00000000000000..4ff8cbed869e34 --- /dev/null +++ b/examples/lighting-app/asr/include/CHIPProjectConfig.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (c) 2021 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 + +/** + * CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY + * + * Enables the use of a hard-coded default Chip device id and credentials if no device id + * is found in Chip NV storage. + * + * This option is for testing only and should be disabled in production releases. + */ +#define CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY 34 + +// 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 + +// define Device type based on the application +#define CHIP_DEVICE_CONFIG_DEVICE_TYPE 257 // 0x0101 Dimmable Bulb + +// 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_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 "1.0" +#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 1 +#endif + +/** + * 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) diff --git a/examples/lighting-app/asr/include/DeviceCallbacks.h b/examples/lighting-app/asr/include/DeviceCallbacks.h new file mode 100644 index 00000000000000..02df92feb1f82a --- /dev/null +++ b/examples/lighting-app/asr/include/DeviceCallbacks.h @@ -0,0 +1,47 @@ +/* + * + * 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. + */ + +/** + * @file DeviceCallbacks.h + * + * Implementations for the DeviceManager callbacks for this application + * + **/ + +#pragma once + +#include "CHIPDeviceManager.h" +#include +#include +#include + +class DeviceCallbacks : public chip::DeviceManager::CHIPDeviceManagerCallbacks +{ +public: + virtual void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + void PostAttributeChangeCallback(chip::EndpointId endpointId, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value) override; + +private: + void OnInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); + void OnOnOffPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); + void OnLevelPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint16_t size, + uint8_t * value); + void OnColorPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); + void OnIdentifyPostAttributeChangeCallback(chip::EndpointId endpointId, chip::AttributeId attributeId, uint8_t * value); +}; diff --git a/examples/lighting-app/asr/src/AppTask.cpp b/examples/lighting-app/asr/src/AppTask.cpp new file mode 100644 index 00000000000000..619a71540c0759 --- /dev/null +++ b/examples/lighting-app/asr/src/AppTask.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2021 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 "CHIPDeviceManager.h" +#include "DeviceCallbacks.h" +#include "LEDWidget.h" +#include "qrcodegen.h" +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "init_Matter.h" +#if CONFIG_ENABLE_CHIP_SHELL +#include "matter_shell.h" +#endif +#include + +namespace { +lega_thread_t sAppTaskHandle; +} // namespace + +LEDWidget lightLED; + +using namespace ::chip; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceManager; +using namespace ::chip::DeviceLayer; +using namespace ::chip::System; + +AppTask AppTask::sAppTask; + +namespace { +constexpr EndpointId kNetworkCommissioningEndpointMain = 0; +constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE; + +app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(kNetworkCommissioningEndpointMain /* Endpoint Id */, + &(NetworkCommissioning::ASRWiFiDriver::GetInstance())); +} // namespace + +void NetWorkCommissioningInstInit() +{ + sWiFiNetworkCommissioningInstance.Init(); + + // We only have network commissioning on endpoint 0. + emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false); +} + +static DeviceCallbacks EchoCallbacks; + +CHIP_ERROR AppTask::StartAppTask() +{ + // Start App task. + OSStatus result = lega_rtos_create_thread(&sAppTaskHandle, 2, APP_TASK_NAME, (lega_thread_function_t) AppTaskMain, + APP_TASK_STACK_SIZE, (lega_thread_arg_t) this); + return (result == kNoErr) ? CHIP_NO_ERROR : CHIP_APPLICATION_ERROR(0x02); +} + +bool IsLightOn() +{ + EmberAfStatus status; + bool on = true; + status = app::Clusters::OnOff::Attributes::OnOff::Get(1, &on); + + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ASR_LOG("Error Read OnOff Attribute 0x%02x\n", status); + } + + return on != false; +} + +uint8_t GetLightLevel() +{ + EmberAfStatus status; + app::DataModel::Nullable currentLevel; + + status = app::Clusters::LevelControl::Attributes::CurrentLevel::Get(1, currentLevel); + + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ASR_LOG("Error Read CurrentLevel Attribute 0x%02x\n", status); + return -1; + } + + if (currentLevel.IsNull()) + { + ASR_LOG("Error currentLevel is null\n"); + return -1; + } + + return currentLevel.Value(); +} + +void led_startup_status() +{ + uint8_t currentLevel; + + if (IsLightOn() == true) + { + currentLevel = GetLightLevel(); + lightLED.Set(1); + lightLED.SetBrightness(currentLevel); + } +} + +void AppTask::AppTaskMain(void * pvParameter) +{ + ASR_LOG("App Task started"); + + if (MatterInitializer::Init_Matter_Stack(MATTER_DEVICE_NAME) != CHIP_NO_ERROR) + appError(CHIP_ERROR_INTERNAL); + + CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance(); + + if (deviceMgr.Init(&EchoCallbacks) != CHIP_NO_ERROR) + appError(CHIP_ERROR_INTERNAL); + + if (MatterInitializer::Init_Matter_Server() != CHIP_NO_ERROR) + appError(CHIP_ERROR_INTERNAL); + + NetWorkCommissioningInstInit(); + + ASR_LOG("Current Firmware Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); + + ConfigurationMgr().LogDeviceConfig(); + + // Print setup info + PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kBLE)); + +#if (LIGHT_SELECT == LIGHT_SELECT_LED) + lightLED.Init(LIGHT_LED); // embedded board light +#elif (LIGHT_SELECT == LIGHT_SELECT_RGB) + lightLED.RGB_init(); +#endif + + /* get led onoff status and level value */ + led_startup_status(); +#if CONFIG_ENABLE_CHIP_SHELL + RegisterLightCommands(); +#endif + /* Delete task */ + lega_rtos_delete_thread(NULL); +} diff --git a/examples/lighting-app/asr/src/DeviceCallbacks.cpp b/examples/lighting-app/asr/src/DeviceCallbacks.cpp new file mode 100644 index 00000000000000..92c962f75702db --- /dev/null +++ b/examples/lighting-app/asr/src/DeviceCallbacks.cpp @@ -0,0 +1,248 @@ +/* + * + * 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. + */ + +/** + * @file DeviceCallbacks.cpp + * + * Implements all the callbacks to the application from the CHIP Stack + * + **/ +#include "DeviceCallbacks.h" +#include "AppConfig.h" +#include "CHIPDeviceManager.h" +#include "LEDWidget.h" +#include "init_OTARequestor.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT || defined CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT +#include "route_hook/asr_route_hook.h" +#endif + +static const char * TAG = "app-devicecallbacks"; + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::System; +using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceManager; +using namespace ::chip::Logging; + +uint32_t identifyTimerCount; +constexpr uint32_t kIdentifyTimerDelayMS = 250; +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +constexpr uint32_t kInitOTARequestorDelaySec = 3; + +void InitOTARequestorHandler(System::Layer * systemLayer, void * appState) +{ + OTAInitializer::Instance().InitOTARequestor(); +} +#endif +void DeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, intptr_t arg) +{ + switch (event->Type) + { + case DeviceEventType::kInternetConnectivityChange: + OnInternetConnectivityChange(event); + break; + + case DeviceEventType::kInterfaceIpAddressChanged: + if ((event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV4_Assigned) || + (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned)) + { + // MDNS server restart on any ip assignment: if link local ipv6 is configured, that + // will not trigger a 'internet connectivity change' as there is no internet + // connectivity. MDNS still wants to refresh its listening interfaces to include the + // newly selected address. + chip::app::DnssdServer::Instance().StartServer(); + + if (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned) + { +#if defined CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT || defined CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT + ChipLogProgress(NotSpecified, "Initializing route hook..."); + asr_route_hook_init(); +#endif + } + } + break; + } +} + +void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + static bool isOTAInitialized = false; +#endif + if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established) + { + ASR_LOG("IPv4 Server ready..."); + chip::app::DnssdServer::Instance().StartServer(); + } + else if (event->InternetConnectivityChange.IPv4 == kConnectivity_Lost) + { + ASR_LOG("Lost IPv4 connectivity..."); + } + if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established) + { + ASR_LOG("IPv6 Server ready..."); + chip::app::DnssdServer::Instance().StartServer(); +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + // Init OTA requestor only when we have gotten IPv6 address + if (!isOTAInitialized) + { + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(kInitOTARequestorDelaySec), + InitOTARequestorHandler, nullptr); + isOTAInitialized = true; + } +#endif + } + else if (event->InternetConnectivityChange.IPv6 == kConnectivity_Lost) + { + ASR_LOG("Lost IPv6 connectivity..."); + } +} + +void DeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, uint8_t type, + uint16_t size, uint8_t * value) +{ + switch (clusterId) + { + case app::Clusters::OnOff::Id: + OnOnOffPostAttributeChangeCallback(endpointId, attributeId, value); + break; + + case app::Clusters::Identify::Id: + OnIdentifyPostAttributeChangeCallback(endpointId, attributeId, value); + break; + + case app::Clusters::LevelControl::Id: + OnLevelPostAttributeChangeCallback(endpointId, attributeId, size, value); + break; + + case app::Clusters::ColorControl::Id: + OnColorPostAttributeChangeCallback(endpointId, attributeId, value); + break; + + default: + ChipLogProgress(Zcl, "Unknown cluster ID: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); + break; + } +} + +void IdentifyTimerHandler(Layer * systemLayer, void * appState) +{ + if (identifyTimerCount) + { + systemLayer->StartTimer(Clock::Milliseconds32(kIdentifyTimerDelayMS), IdentifyTimerHandler, appState); + // Decrement the timer count. + identifyTimerCount--; + } +} + +extern LEDWidget lightLED; + +void DeviceCallbacks::OnOnOffPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + VerifyOrExit(attributeId == app::Clusters::OnOff::Attributes::OnOff::Id, + ChipLogError(DeviceLayer, TAG, "Unhandled Attribute ID: '0x%04x", attributeId)); + VerifyOrExit(endpointId == 1 || endpointId == 2, + ChipLogError(DeviceLayer, TAG, "Unexpected EndPoint ID: `0x%02x'", endpointId)); + + lightLED.Set(*value); + +exit: + return; +} + +void DeviceCallbacks::OnLevelPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint16_t size, + uint8_t * value) +{ + VerifyOrExit(attributeId == app::Clusters::LevelControl::Attributes::CurrentLevel::Id, + ChipLogError(DeviceLayer, TAG, "Unhandled Attribute ID: '0x%04x", attributeId)); + VerifyOrExit(endpointId == 1 || endpointId == 2, + ChipLogError(DeviceLayer, TAG, "Unexpected EndPoint ID: `0x%02x'", endpointId)); + + if (size == 1) + { + uint8_t tmp = *value; + ChipLogProgress(Zcl, "New level: %u ", tmp); + lightLED.SetBrightness(tmp); + } + else + { + ChipLogError(Zcl, "wrong length for level: %d\n", size); + } + +exit: + return; +} + +void DeviceCallbacks::OnColorPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + using namespace app::Clusters::ColorControl::Attributes; + + uint8_t hue, saturation; + + if ((attributeId != CurrentHue::Id) && (attributeId != CurrentSaturation::Id)) + { + ChipLogProgress(Zcl, "Unknown attribute ID: %" PRIx32, attributeId); + return; + } + + if (attributeId == CurrentHue::Id) + { + hue = *value; + CurrentSaturation::Get(endpointId, &saturation); + } + if (attributeId == CurrentSaturation::Id) + { + saturation = *value; + CurrentHue::Get(endpointId, &hue); + } + + ASR_LOG("New hue: %d, New saturation: %d\n", hue, saturation); + + lightLED.SetColor(hue, saturation); +} + +void DeviceCallbacks::OnIdentifyPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value) +{ + VerifyOrExit(attributeId == app::Clusters::Identify::Attributes::IdentifyTime::Id, + ChipLogError(DeviceLayer, "[%s] Unhandled Attribute ID: '0x%04lx", TAG, attributeId)); + VerifyOrExit(endpointId == 1, ChipLogError(DeviceLayer, "[%s] Unexpected EndPoint ID: `0x%02x'", TAG, endpointId)); + + // timerCount represents the number of callback executions before we stop the timer. + // value is expressed in seconds and the timer is fired every 250ms, so just multiply value by 4. + // Also, we want timerCount to be odd number, so the ligth state ends in the same state it starts. + identifyTimerCount = (*value) * 4; + + DeviceLayer::SystemLayer().CancelTimer(IdentifyTimerHandler, this); + DeviceLayer::SystemLayer().StartTimer(Clock::Milliseconds32(kIdentifyTimerDelayMS), IdentifyTimerHandler, this); + +exit: + return; +} diff --git a/examples/lighting-app/asr/src/main.cpp b/examples/lighting-app/asr/src/main.cpp new file mode 100644 index 00000000000000..b697014484e13e --- /dev/null +++ b/examples/lighting-app/asr/src/main.cpp @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 2021 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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "AppConfig.h" +#include "init_asrPlatform.h" +#include + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::DeviceLayer; + +volatile int apperror_cnt; +// ================================================================================ +// App Error +//================================================================================= +void appError(int err) +{ + ASR_LOG("!!!!!!!!!!!! App Critical Error: %d !!!!!!!!!!!", err); + lega_rtos_declare_critical(); + lega_rtos_enter_critical(); + while (1) + ; +} + +void appError(CHIP_ERROR error) +{ + appError(static_cast(error.AsInteger())); +} + +// ================================================================================ +// FreeRTOS Callbacks +// ================================================================================ +extern "C" void vApplicationIdleHook(void) +{ + // FreeRTOS Idle callback +} + +// ================================================================================ +// Main Code +// ================================================================================ +int main(void) +{ + init_asrPlatform(); + + CHIP_ERROR ret = GetAppTask().StartAppTask(); + if (ret != CHIP_NO_ERROR) + { + ASR_LOG("GetAppTask().Init() failed"); + appError(ret); + } + /* Start the FreeRTOS scheduler */ + vTaskStartScheduler(); + + chip::Platform::MemoryShutdown(); + PlatformMgr().StopEventLoopTask(); + PlatformMgr().Shutdown(); + + // Should never get here. + ASR_LOG("vTaskStartScheduler() failed"); + appError(ret); +} diff --git a/examples/lighting-app/asr/third_party/connectedhomeip b/examples/lighting-app/asr/third_party/connectedhomeip new file mode 120000 index 00000000000000..11a54ed360106c --- /dev/null +++ b/examples/lighting-app/asr/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/examples/platform/asr/BUILD.gn b/examples/platform/asr/BUILD.gn new file mode 100755 index 00000000000000..432d63cff64aa2 --- /dev/null +++ b/examples/platform/asr/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2023 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/asr.gni") +import("//build_overrides/chip.gni") + +import("${asr_sdk_build_root}/asr_sdk.gni") + +config("chip_examples_project_config") { + include_dirs = [ "project_include" ] +} diff --git a/examples/platform/asr/CHIPDeviceManager.cpp b/examples/platform/asr/CHIPDeviceManager.cpp new file mode 100644 index 00000000000000..8587b0b65abde2 --- /dev/null +++ b/examples/platform/asr/CHIPDeviceManager.cpp @@ -0,0 +1,76 @@ +/* + * + * 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 CHIP Device Interface that is used by + * applications to interact with the CHIP stack + * + */ + +#include + +#include "CHIPDeviceManager.h" +#include +#include +#include +#include +#include + +using namespace ::chip; + +namespace chip { + +namespace DeviceManager { + +using namespace ::chip::DeviceLayer; + +void CHIPDeviceManager::CommonDeviceEventHandler(const ChipDeviceEvent * event, intptr_t arg) +{ + CHIPDeviceManagerCallbacks * cb = reinterpret_cast(arg); + if (cb != nullptr) + { + cb->DeviceEventCallback(event, reinterpret_cast(cb)); + } +} + +CHIP_ERROR CHIPDeviceManager::Init(CHIPDeviceManagerCallbacks * cb) +{ + mCB = cb; + + PlatformMgr().AddEventHandler(CHIPDeviceManager::CommonDeviceEventHandler, reinterpret_cast(cb)); + + return CHIP_NO_ERROR; +} +} // namespace DeviceManager +} // namespace chip + +void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value) +{ + chip::DeviceManager::CHIPDeviceManagerCallbacks * cb = + chip::DeviceManager::CHIPDeviceManager::GetInstance().GetCHIPDeviceManagerCallbacks(); + + ChipLogProgress(Zcl, + "MatterPostAttributeChangeCallback - Cluster ID: " ChipLogFormatMEI + ", EndPoint ID: '0x%02x', Attribute ID: " ChipLogFormatMEI, + ChipLogValueMEI(path.mClusterId), path.mEndpointId, ChipLogValueMEI(path.mAttributeId)); + + if (cb != nullptr) + { + cb->PostAttributeChangeCallback(path.mEndpointId, path.mClusterId, path.mAttributeId, type, size, value); + } +} diff --git a/examples/platform/asr/CHIPDeviceManager.h b/examples/platform/asr/CHIPDeviceManager.h new file mode 100644 index 00000000000000..0f4af78bc756b2 --- /dev/null +++ b/examples/platform/asr/CHIPDeviceManager.h @@ -0,0 +1,124 @@ +/* + * + * 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 contains definitions for the CHIP DeviceManager Interface + * + * This object will co-ordinate multiple activities such as + * initialisation, rendezvous, session mgmt and other such + * activities within the CHIP stack. This is a singleton object. + */ + +#pragma once + +#include +#include +#include + +#include + +#include +#include + +#include + +namespace chip { +namespace DeviceManager { + +/** + * @brief + * This class provides a skeleton for all the callback functions. The functions will be + * called by other objects within the CHIP stack for specific events. + * Applications interested in receiving specific callbacks can specialize this class and handle + * these events in their implementation of this class. + */ +class CHIPDeviceManagerCallbacks +{ +public: + /** + * @brief + * Called when CHIP Device events (PublicEventTypes) are triggered. + * + * @param event ChipDeviceEvent that occurred + * @param arg arguments specific to the event, if any + */ + virtual void DeviceEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) {} + + /** + * @brief + * Called after an attribute has been changed + * + * @param endpoint endpoint id + * @param clusterID cluster id + * @param attributeId attribute id that was changed + * @param mask mask of the attribute + * @param manufacturerCode manufacturer code + * @param type attribute type + * @param size size of the attribute + * @param value pointer to the new value + */ + virtual void PostAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value) + {} + virtual ~CHIPDeviceManagerCallbacks() {} +}; + +/** + * @brief + * A common class that drives other components of the CHIP stack + */ +class DLL_EXPORT CHIPDeviceManager +{ +public: + CHIPDeviceManager(const CHIPDeviceManager &) = delete; + CHIPDeviceManager(const CHIPDeviceManager &&) = delete; + CHIPDeviceManager & operator=(const CHIPDeviceManager &) = delete; + + static CHIPDeviceManager & GetInstance() + { + static CHIPDeviceManager instance; + return instance; + } + + /** + * @brief + * Initialise CHIPDeviceManager + * + * @param cb Application's instance of the CHIPDeviceManagerCallbacks for consuming events + */ + CHIP_ERROR Init(CHIPDeviceManagerCallbacks * cb); + + /** + * @brief + * Fetch a pointer to the registered CHIPDeviceManagerCallbacks object. + * + */ + CHIPDeviceManagerCallbacks * GetCHIPDeviceManagerCallbacks() { return mCB; } + + /** + * Use internally for registration of the ChipDeviceEvents + */ + static void CommonDeviceEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + +private: + CHIPDeviceManagerCallbacks * mCB = nullptr; + CHIPDeviceManager() {} +}; + +} // namespace DeviceManager +} // namespace chip diff --git a/examples/platform/asr/LEDWidget.cpp b/examples/platform/asr/LEDWidget.cpp new file mode 100644 index 00000000000000..f89f502f7ff62f --- /dev/null +++ b/examples/platform/asr/LEDWidget.cpp @@ -0,0 +1,280 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LEDWidget.h" +#ifdef CFG_PLF_RV32 +#include "asr_gpio.h" +#include "asr_pinmux.h" +#include "asr_pwm.h" +#define duet_pwm_dev_t asr_pwm_dev_t +#define duet_pwm_config_t asr_pwm_config_t +#define duet_pwm_para_chg asr_pwm_para_chg +#define duet_pwm_init asr_pwm_init +#define duet_pwm_start asr_pwm_start +#else +#include "duet_gpio.h" +#include "duet_pinmux.h" +#include "duet_pwm.h" +#endif +#include "AppConfig.h" +#include + +/******************************************************************************* + * Macro Definitions + *******************************************************************************/ +/* Allowed TCPWM compare value for maximum brightness */ +#define LED_MAX_BRIGHTNESS (100u) + +/* Allowed TCPWM compare value for minimum brightness*/ +#define LED_MIN_BRIGHTNESS (0u) + +#define PWM_LED_FREQ_HZ (1000u) /* in Hz */ + +/* subtracting from 100 since the LED is connected in active low configuration */ +#define GET_DUTY_CYCLE(x) (100 - x) + +// PWM period in micro seconds +#define LED_PWM_PERIOD_US (255u) + +static void show_pwm(duet_pwm_dev_t * pwm_dev, uint8_t val) +{ + duet_pwm_config_t pwm_cfg; + + if (val < LED_MIN_BRIGHTNESS) + val = LED_MIN_BRIGHTNESS; + pwm_cfg.duty_cycle = (float) (val) / LED_PWM_PERIOD_US; + pwm_cfg.freq = PWM_LED_FREQ_HZ; + + duet_pwm_para_chg(pwm_dev, pwm_cfg); +} + +static void init_pwm(duet_pwm_dev_t * pwm_dev, uint8_t ledNum, uint8_t val) +{ + pwm_dev->port = ledNum; + pwm_dev->config.duty_cycle = val; + pwm_dev->config.freq = PWM_LED_FREQ_HZ; + pwm_dev->priv = NULL; + duet_pwm_init(pwm_dev); +} + +void LEDWidget::Init(uint8_t ledNum) +{ + mLastChangeTimeMS = 0; + mBlinkOnTimeMS = 0; + mBlinkOffTimeMS = 0; + mState = 0; + mbrightness = LED_MIN_BRIGHTNESS; + mHue = 0; + mSaturation = 0; + + if (ledNum == LIGHT_RGB_GREEN) + { +#ifdef CFG_PLF_RV32 + asr_pinmux_config(LIGHT_RGB_RED_PAD, PF_PWM); +#endif + init_pwm(&pwm_led_g, ledNum, LED_MIN_BRIGHTNESS); + } + else if (ledNum == LIGHT_RGB_BLUE) + { +#ifdef CFG_PLF_RV32 + asr_pinmux_config(LIGHT_RGB_BLUE_PAD, PF_PWM); +#endif + init_pwm(&pwm_led_b, ledNum, LED_MIN_BRIGHTNESS); + } + else + { +#ifdef CFG_PLF_RV32 + asr_pinmux_config(LIGHT_RGB_GREEN_PAD, PF_PWM); +#endif + init_pwm(&pwm_led, ledNum, LED_MIN_BRIGHTNESS); + } +} + +void LEDWidget::Invert(void) +{ + Set(!mState); +} + +void LEDWidget::Set(bool state) +{ + mLastChangeTimeMS = mBlinkOnTimeMS = mBlinkOffTimeMS = 0; + DoSet(state); +} + +bool LEDWidget::Get() +{ + return mState; +} + +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 = ((mState) ? mBlinkOnTimeMS : mBlinkOffTimeMS); + uint64_t nextChangeTimeMS = mLastChangeTimeMS + stateDurMS; + + if (nextChangeTimeMS < nowMS) + { + DoSet(!mState); + mLastChangeTimeMS = nowMS; + } + } +} + +void LEDWidget::DoSet(bool state) +{ + if (mState != state) + { + (state) ? PWM_start() : PWM_stop(); + } + mState = state; +} + +void LEDWidget::RGB_init() +{ + Init(LIGHT_RGB_RED); // red light of RGB + Init(LIGHT_RGB_GREEN); // green light of RGB + Init(LIGHT_RGB_BLUE); // blue light of RGB +} + +void LEDWidget::PWM_start() +{ + if (!mState) + { + /* Start PWM to turn the LED on */ + if (0 != duet_pwm_start(&pwm_led)) + { + ASR_LOG("PWM failed to start!"); + } + +#if (LIGHT_SELECT == LIGHT_SELECT_RGB) + /* Start PWM to turn the LED on */ + if (0 != duet_pwm_start(&pwm_led_g)) + { + ASR_LOG("PWM failed to start!"); + } + + /* Start PWM to turn the LED on */ + if (0 != duet_pwm_start(&pwm_led_b)) + { + ASR_LOG("PWM failed to start!"); + } +#endif + mState = 1; + } +} + +void LEDWidget::PWM_stop() +{ + SetBrightness(LED_MIN_BRIGHTNESS); + mbrightness = LED_MIN_BRIGHTNESS; + mState = 0; +} + +void LEDWidget::SetBrightness(uint8_t brightness) +{ + mbrightness = brightness; + SetColor(mHue, mSaturation); +} + +void LEDWidget::SetColor(uint8_t Hue, uint8_t Saturation) +{ + uint8_t red, green, blue; + uint8_t sSaturation, sbrightness; + uint16_t sHue; + + sbrightness = (mState) ? mbrightness : 0; + + sHue = static_cast(Hue) * 360 / 254; // sHue [0, 360] + sSaturation = static_cast(Saturation) * 100 / 254; // sSaturation [0 , 100] + + HSB2rgb(sHue, sSaturation, sbrightness, red, green, blue); + ASR_LOG("brightness: %d, red: %d, green: %d, blue: %d", sbrightness, red, green, blue); + + mHue = Hue; + mSaturation = Saturation; + + showRGB(red, green, blue); +} + +void LEDWidget::HSB2rgb(uint16_t Hue, uint8_t Saturation, uint8_t brightness, uint8_t & red, uint8_t & green, uint8_t & blue) +{ + uint16_t i = Hue / 60; + uint16_t rgb_max = brightness; + uint16_t rgb_min = rgb_max * (100 - Saturation) / 100; + uint16_t diff = Hue % 60; + uint16_t rgb_adj = (rgb_max - rgb_min) * diff / 60; + + switch (i) + { + case 0: + red = rgb_max; + green = rgb_min + rgb_adj; + blue = rgb_min; + break; + case 1: + red = rgb_max - rgb_adj; + green = rgb_max; + blue = rgb_min; + break; + case 2: + red = rgb_min; + green = rgb_max; + blue = rgb_min + rgb_adj; + break; + case 3: + red = rgb_min; + green = rgb_max - rgb_adj; + blue = rgb_max; + break; + case 4: + red = rgb_min + rgb_adj; + green = rgb_min; + blue = rgb_max; + break; + default: + red = rgb_max; + green = rgb_min; + blue = rgb_max - rgb_adj; + break; + } +} + +void LEDWidget::showRGB(uint8_t red, uint8_t green, uint8_t blue) +{ + show_pwm(&pwm_led, red); + +#if (LIGHT_SELECT == LIGHT_SELECT_RGB) + show_pwm(&pwm_led_g, green); + + show_pwm(&pwm_led_b, blue); +#endif +} diff --git a/examples/platform/asr/LEDWidget.h b/examples/platform/asr/LEDWidget.h new file mode 100644 index 00000000000000..028a852fba1933 --- /dev/null +++ b/examples/platform/asr/LEDWidget.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#ifdef CFG_PLF_RV32 +#include "asr_pwm.h" +#define duet_pwm_dev_t asr_pwm_dev_t +#else +#include "duet_pwm.h" +#endif +#ifdef __cplusplus +extern "C" { +#endif +void RGB_setup_HSB(uint8_t Hue, uint8_t Saturation); +#ifdef __cplusplus +} +#endif + +#define LIGHT_SELECT_LED 1 +#define LIGHT_SELECT_RGB 2 +#define LIGHT_SELECT LIGHT_SELECT_RGB + +#define LIGHT_RGB_RED PWM_OUTPUT_CH6 +#define LIGHT_RGB_GREEN PWM_OUTPUT_CH4 +#define LIGHT_RGB_BLUE PWM_OUTPUT_CH1 + +#define LIGHT_RGB_RED_PAD PAD7 +#define LIGHT_RGB_GREEN_PAD PAD6 +#define LIGHT_RGB_BLUE_PAD PAD10 + +class LEDWidget +{ +public: + static void InitGpio(void); + void Init(uint8_t port); + void Set(bool state); + bool Get(void); + void Invert(void); + void Blink(uint32_t changeRateMS); + void Blink(uint32_t onTimeMS, uint32_t offTimeMS); + void Animate(); + void PWM_start(); + void PWM_stop(); + void RGB_init(); + void SetBrightness(uint8_t brightness); + void SetColor(uint8_t Hue, uint8_t Saturation); + void HSB2rgb(uint16_t Hue, uint8_t Saturation, uint8_t brightness, uint8_t & red, uint8_t & green, uint8_t & blue); + void showRGB(uint8_t red, uint8_t green, uint8_t blue); + +private: + uint64_t mLastChangeTimeMS = 0; + uint32_t mBlinkOnTimeMS = 0; + uint32_t mBlinkOffTimeMS = 0; + bool mState = 0; + uint8_t mbrightness = 0; + + uint8_t mHue; + uint8_t mSaturation; + duet_pwm_dev_t pwm_led; + duet_pwm_dev_t pwm_led_g; + duet_pwm_dev_t pwm_led_b; + void DoSet(bool state); +}; diff --git a/examples/platform/asr/args.gni b/examples/platform/asr/args.gni new file mode 100755 index 00000000000000..53604116cd174f --- /dev/null +++ b/examples/platform/asr/args.gni @@ -0,0 +1,21 @@ +# Copyright (c) 2023 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/asr/init_Matter.cpp b/examples/platform/asr/init_Matter.cpp new file mode 100644 index 00000000000000..8f46ac4f9ed423 --- /dev/null +++ b/examples/platform/asr/init_Matter.cpp @@ -0,0 +1,121 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppConfig.h" +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_ENABLE_CHIP_SHELL +#include +#endif +#include + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::DeviceLayer; +using namespace ::chip::Credentials; +using namespace ::chip::System; + +namespace { +ASRFactoryDataProvider sFactoryDataProvider; +} // namespace + +chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; + +CHIP_ERROR MatterInitializer::Matter_Task_Config(lega_task_config_t * cfg) +{ + lega_rtos_get_chip_task_cfg(cfg); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR MatterInitializer::Init_Matter_Stack(const char * appName) +{ + // mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); + + ASR_LOG("==================================================\r\n"); + ASR_LOG("%s starting\r\n", appName); + ASR_LOG("==================================================\r\n"); + + CHIP_ERROR err = CHIP_NO_ERROR; + + err = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); + if (err != CHIP_NO_ERROR) + { + ASR_LOG("PersistedStorage::KeyValueStoreMgrImpl().Init() failed"); + appError(err); + } + + SetCommissionableDataProvider(&sFactoryDataProvider); + //============================================== + // Init Matter Stack + //============================================== + ASR_LOG("Init CHIP Stack"); + // Init Chip memory management before the stack + err = chip::Platform::MemoryInit(); + ReturnErrorOnFailure(err); + + err = PlatformMgr().InitChipStack(); + ReturnErrorOnFailure(err); + + err = sFactoryDataProvider.Init(); + ReturnErrorOnFailure(err); + + SetDeviceInstanceInfoProvider(&sFactoryDataProvider); + + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(appName); + + if (CONFIG_NETWORK_LAYER_BLE) + { + ConnectivityMgr().SetBLEAdvertisingEnabled(true); + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR MatterInitializer::Init_Matter_Server(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Init Matter Server and Start Event Loop + chip::DeviceLayer::PlatformMgr().LockChipStack(); + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); + chip::Server::GetInstance().Init(initParams); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + + // Initialize device attestation config + SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); + + ASR_LOG("Starting Platform Manager Event Loop"); + // // Start a task to run the CHIP Device event loop. + err = PlatformMgr().StartEventLoopTask(); + ReturnErrorOnFailure(err); + +#if CONFIG_ENABLE_CHIP_SHELL + chip::LaunchShell(); +#endif + + return CHIP_NO_ERROR; +} diff --git a/examples/platform/asr/init_Matter.h b/examples/platform/asr/init_Matter.h new file mode 100644 index 00000000000000..d6bea07bee8036 --- /dev/null +++ b/examples/platform/asr/init_Matter.h @@ -0,0 +1,30 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include + +class MatterInitializer +{ +public: + static CHIP_ERROR Init_Matter_Stack(const char * appName); + static CHIP_ERROR Init_Matter_Server(void); + static CHIP_ERROR Matter_Task_Config(lega_task_config_t * cfg); +}; diff --git a/examples/platform/asr/init_OTARequestor.cpp b/examples/platform/asr/init_OTARequestor.cpp new file mode 100644 index 00000000000000..3bcad294bd162f --- /dev/null +++ b/examples/platform/asr/init_OTARequestor.cpp @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "init_OTARequestor.h" +#include "app/clusters/ota-requestor/DefaultOTARequestorStorage.h" +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::DeviceLayer; + +namespace { +DefaultOTARequestor gRequestorCore; +DefaultOTARequestorStorage gRequestorStorage; +ExtendedOTARequestorDriver gRequestorUser; +BDXDownloader gDownloader; +ASROTAImageProcessor gImageProcessor; +chip::ota::DefaultOTARequestorUserConsent gUserConsentProvider; +static chip::ota::UserConsentState gUserConsentState = chip::ota::UserConsentState::kGranted; +} // namespace + +#define OTA_PERIODIC_TIMEOUT 86400 // 24 * 60 * 60 + +extern "C" void asrQueryImageCmdHandler() +{ + ChipLogProgress(DeviceLayer, "Calling asrQueryImageCmdHandler"); + PlatformMgr().ScheduleWork([](intptr_t) { GetRequestorInstance()->TriggerImmediateQuery(); }); +} + +extern "C" void asrApplyUpdateCmdHandler() +{ + ChipLogProgress(DeviceLayer, "Calling asrApplyUpdateCmdHandler"); + PlatformMgr().ScheduleWork([](intptr_t) { GetRequestorInstance()->ApplyUpdate(); }); +} + +void OTAInitializer::InitOTARequestor(void) +{ + SetRequestorInstance(&gRequestorCore); + ConfigurationMgr().StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + // Set server instance used for session establishment + gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + gImageProcessor.SetOTADownloader(&gDownloader); + // Connect the Downloader and Image Processor objects + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + + gRequestorUser.SetPeriodicQueryTimeout(OTA_PERIODIC_TIMEOUT); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + if (gUserConsentState != chip::ota::UserConsentState::kUnknown) + { + gUserConsentProvider.SetUserConsentState(gUserConsentState); + gRequestorUser.SetUserConsentDelegate(&gUserConsentProvider); + } + ChipLogProgress(DeviceLayer, "Current Software Version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + ChipLogProgress(DeviceLayer, "Current Software Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); +} + +void OTAInitializer::ReloadQueryTimeout(uint32_t timeout) +{ + if (timeout > 0) + { + gRequestorUser.SetPeriodicQueryTimeout(timeout); + gRequestorUser.RekickPeriodicQueryTimer(); + } +} diff --git a/examples/platform/asr/init_OTARequestor.h b/examples/platform/asr/init_OTARequestor.h new file mode 100755 index 00000000000000..6975da8fb1a12d --- /dev/null +++ b/examples/platform/asr/init_OTARequestor.h @@ -0,0 +1,30 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "stdint.h" + +class OTAInitializer +{ +public: + static OTAInitializer & Instance(void) + { + static OTAInitializer sInitOTA; + return sInitOTA; + } + void InitOTARequestor(void); + void ReloadQueryTimeout(uint32_t timeout); +}; diff --git a/examples/platform/asr/init_asrPlatform.cpp b/examples/platform/asr/init_asrPlatform.cpp new file mode 100644 index 00000000000000..b91419812b88a9 --- /dev/null +++ b/examples/platform/asr/init_asrPlatform.cpp @@ -0,0 +1,163 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file provides the function to initialize the ASR platform. + */ + +#include "AppConfig.h" +#include +#include + +#include +#include +#include + +#include "lega_wlan_api.h" +#include "soc_init.h" +#ifdef CFG_PLF_RV32 +#include "asr_flash_kv.h" +#include "asr_pinmux.h" +#include "asr_sec_hw_common.h" +#include "asr_uart.h" +#else +#include "duet_flash_kv.h" +#include "duet_pinmux.h" +#include "duet_uart.h" +#include "duet_version.h" +#endif +#include "lega_ota_utils.h" +#include "lega_rtos_api.h" +#include "printf_uart.h" +#include "tcpip.h" +#if (CFG_EASY_LOG_ENABLE == 1) +#include "elog.h" +#include "elog_cfg.h" +#endif + +#ifdef CFG_PLF_RV32 +#define LEGA_UART0_INDEX UART0_INDEX +#define LEGA_UART1_INDEX UART1_INDEX +#define LEGA_UART2_INDEX UART2_INDEX +#define duet_pinmux_config asr_pinmux_config +#define duet_uart_init printf_uart_init +#define duet_flash_kv_init alto_flash_kv_init +#else +#define LEGA_UART0_INDEX DUET_UART0_INDEX +#define LEGA_UART1_INDEX DUET_UART1_INDEX +#define LEGA_UART2_INDEX DUET_UART2_INDEX +#endif + +#define UART1_TX_PIN PAD2 +#define UART1_RX_PIN PAD3 + +#ifdef CFG_PLF_RV32 +extern asr_uart_dev_t lega_at_uart; +#else +extern duet_uart_dev_t lega_at_uart; +#endif + +#ifdef __cplusplus +extern "C" { +#endif +void lega_sram_rf_pta_init(void); +void lega_recovery_phy_fsm_config(void); +void lega_wlan_efuse_read(void); +int lega_wlan_init(void); +void ota_roll_back_pro(void); +int32_t duet_flash_kv_init(void); +void lega_at_cmd_register_all(void); +int lega_at_init(void); +void at_handle_uartirq(char ch); +int asr_security_engine_init(); +void at_uart_init(void); +#ifdef __cplusplus +} +#endif + +void at_uart_init(void) +{ + memset(&lega_at_uart, 0, sizeof(lega_at_uart)); + + lega_at_uart.config.baud_rate = UART_BAUDRATE_115200; + lega_at_uart.config.data_width = DATA_8BIT; + lega_at_uart.config.flow_control = FLOW_CTRL_DISABLED; + lega_at_uart.config.parity = PARITY_NO; + lega_at_uart.config.stop_bits = STOP_1BIT; + lega_at_uart.config.mode = TX_RX_MODE; + lega_at_uart.port = UART1_INDEX; + + duet_pinmux_config(UART1_TX_PIN, PF_UART1); + duet_pinmux_config(UART1_RX_PIN, PF_UART1); + + // register uart callback func for receiving at command + lega_at_uart.priv = (void *) (at_handle_uartirq); + duet_uart_init(&lega_at_uart); +} + +void init_asrPlatform(void) +{ + // don't run any code before soc_pre_init. + soc_pre_init(); + + soc_init(); + + duet_flash_kv_init(); + + // uart init and register uart for receiving at command + at_uart_init(); + + // ota roll back,just for flash_remapping + ota_roll_back_pro(); + + // register uart for printf log, the used uart should be init before. + printf_uart_register(LEGA_UART1_INDEX); + // register uart for at log, the used uart should be init before. + printf2_uart_register(LEGA_UART1_INDEX); + + // printf("\napp version: %s\n",LEGA_VERSION_STR); + + /* set EasyLogger log format */ +#if (CFG_EASY_LOG_ENABLE == 1) + elog_init(); + elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME); + elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME); + elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME); + elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME); + elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME); + elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME); + elog_start(); +#endif + + lega_wlan_efuse_read(); + + lega_sram_rf_pta_init(); + + lega_recovery_phy_fsm_config(); + + asr_security_engine_init(); +#if !CONFIG_ENABLE_CHIP_SHELL + lega_at_init(); +#endif + lega_at_cmd_register_all(); + + lega_wlan_init(); + + tcpip_init(NULL, NULL); +} diff --git a/examples/platform/asr/init_asrPlatform.h b/examples/platform/asr/init_asrPlatform.h new file mode 100755 index 00000000000000..33dc6337dda189 --- /dev/null +++ b/examples/platform/asr/init_asrPlatform.h @@ -0,0 +1,26 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file provides the function to initialize the ASR platform. + */ + +#pragma once + +void init_asrPlatform(void); diff --git a/examples/platform/asr/shell/launch_shell.cpp b/examples/platform/asr/shell/launch_shell.cpp new file mode 100644 index 00000000000000..a937d1ea48ddbe --- /dev/null +++ b/examples/platform/asr/shell/launch_shell.cpp @@ -0,0 +1,42 @@ +/* + * + * 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 "launch_shell.h" + +#include "lega_rtos_api.h" + +#include + +namespace { + +void MatterShellTask(void * args) +{ + chip::Shell::Engine::Root().RunMainLoop(); +} + +} // namespace + +namespace chip { + +void LaunchShell() +{ + chip::Shell::Engine::Root().Init(); + + lega_rtos_create_thread(NULL, 1, "matter_shell", (lega_thread_function_t) MatterShellTask, 2048, 0); +} + +} // namespace chip diff --git a/examples/platform/asr/shell/launch_shell.h b/examples/platform/asr/shell/launch_shell.h new file mode 100755 index 00000000000000..604584b58982bd --- /dev/null +++ b/examples/platform/asr/shell/launch_shell.h @@ -0,0 +1,24 @@ +/* + * + * 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 + +namespace chip { + +void LaunchShell(); + +} diff --git a/examples/platform/asr/shell/matter_shell.cpp b/examples/platform/asr/shell/matter_shell.cpp new file mode 100644 index 00000000000000..55a66b31cf0eaf --- /dev/null +++ b/examples/platform/asr/shell/matter_shell.cpp @@ -0,0 +1,142 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file provides the Shell implementation of Matter. + * It can be also used in ASR AT Command implementation. + */ + +#include "matter_shell.h" +#include "AppConfig.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; + +#if CONFIG_ENABLE_CHIP_SHELL +#include "lib/shell/Engine.h" + +using chip::Shell::Engine; +using chip::Shell::shell_command_t; +using chip::Shell::streamer_get; +using chip::Shell::streamer_printf; +#endif + +void asr_matter_reset(Reset_t type) +{ + if (type == WIFI_RESET) + { + ConnectivityMgr().ClearWiFiStationProvision(); + chip::Server::GetInstance().GetFabricTable().DeleteAllFabrics(); + chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); + } + else if (type == FACTORY_RESET) + { + chip::Server::GetInstance().ScheduleFactoryReset(); + } + else if (type == COMMISSIONING_RESET) + { + chip::Server::GetInstance().GetFabricTable().DeleteAllFabrics(); + auto & commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager(); + commissionMgr.OpenBasicCommissioningWindow(commissionMgr.MaxCommissioningTimeout(), + CommissioningWindowAdvertisement::kDnssdOnly); + } +} + +void ShutdownChip() +{ + Server::GetInstance().Shutdown(); + PlatformMgr().StopEventLoopTask(); + PlatformMgr().Shutdown(); +} + +void asr_matter_onoff(int value) +{ + ChipLogProgress(Zcl, "updating on/off = %d", value); + + EmberAfStatus status = chip::app::Clusters::OnOff::Attributes::OnOff::Set( + /* endpoint ID */ 1, (uint8_t *) &value); + + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "ERR: updating on/off %x", status); + } +} + +void asr_matter_sensors(bool enable, int temp, int humi, int pressure) +{ +#if ASR_BOARD_ENABLE_SENSORS + if (enable) + { + chip::app::Clusters::TemperatureMeasurement::Attributes::MeasuredValue::Set( + /* endpoint ID */ 1, static_cast(temp)); + + chip::app::Clusters::RelativeHumidityMeasurement::Attributes::MeasuredValue::Set( + /* endpoint ID */ 1, static_cast(humi)); + + chip::app::Clusters::PressureMeasurement::Attributes::MeasuredValue::Set( + /* endpoint ID */ 1, static_cast(pressure)); + } +#else + ChipLogProgress(Zcl, "Sensor is not supported!"); +#endif +} + +void asr_matter_ota(uint32_t timeout) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + OTAInitializer::Instance().ReloadQueryTimeout(timeout); +#else + ChipLogProgress(Zcl, "OTA is not supported!"); +#endif +} + +#if CONFIG_ENABLE_CHIP_SHELL +static CHIP_ERROR sLightCommandHandler(int argc, char ** argv) +{ + if (argc == 1 && strcmp(argv[0], "on") == 0) + { + asr_matter_onoff(1); + return CHIP_NO_ERROR; + } + if (argc == 1 && strcmp(argv[0], "off") == 0) + { + asr_matter_onoff(0); + return CHIP_NO_ERROR; + } + streamer_printf(streamer_get(), "Usage: OnOff [on|off]"); + return CHIP_NO_ERROR; +} + +void RegisterLightCommands() +{ + static const shell_command_t sLightCommand = { sLightCommandHandler, "OnOff", "OnOff commands. Usage: OnOff [on|off]" }; + Engine::Root().RegisterCommands(&sLightCommand, 1); +} +#endif diff --git a/examples/platform/asr/shell/matter_shell.h b/examples/platform/asr/shell/matter_shell.h new file mode 100644 index 00000000000000..e0f2c86f2818aa --- /dev/null +++ b/examples/platform/asr/shell/matter_shell.h @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file provides the Shell implementation of Matter. + * It can be also used in ASR AT Command implementation. + */ + +#ifndef __MATTER_SHELL_H__ +#define __MATTER_SHELL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + WIFI_RESET = 0, + FACTORY_RESET, + COMMISSIONING_RESET, +} Reset_t; + +void ShutdownChip(); +void asr_matter_reset(Reset_t type); +void asr_matter_onoff(int value); +void asr_matter_sensors(bool enable, int temp, int humi, int pressure); +void asr_matter_ota(uint32_t timeout); +#if CONFIG_ENABLE_CHIP_SHELL +void RegisterLightCommands(); +#endif +#ifdef __cplusplus +} +#endif +#endif // __MATTER_SHELL_H__ diff --git a/scripts/build/BUILD.gn b/scripts/build/BUILD.gn index b19ffcd8d78a7f..11ea4e9b721e84 100644 --- a/scripts/build/BUILD.gn +++ b/scripts/build/BUILD.gn @@ -43,6 +43,7 @@ pw_python_package("build_examples") { "builders/__init__.py", "builders/ameba.py", "builders/android.py", + "builders/asr.py", "builders/bouffalolab.py", "builders/builder.py", "builders/efr32.py", diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 49a6d74cbd2f43..7c62db1941eff6 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -14,6 +14,7 @@ from builders.ameba import AmebaApp, AmebaBoard, AmebaBuilder from builders.android import AndroidApp, AndroidBoard, AndroidBuilder, AndroidProfile +from builders.asr import ASRApp, ASRBoard, ASRBuilder from builders.bouffalolab import BouffalolabApp, BouffalolabBoard, BouffalolabBuilder from builders.cc13x2x7_26x2x7 import cc13x2x7_26x2x7App, cc13x2x7_26x2x7Builder from builders.cc32xx import cc32xxApp, cc32xxBuilder @@ -371,6 +372,28 @@ def BuildAmebaTarget(): return target +def BuildASRTarget(): + target = BuildTarget('asr', ASRBuilder) + + # board + target.AppendFixedTargets([ + TargetPart('asr582x', board=ASRBoard.ASR582X), + TargetPart('asr595x', board=ASRBoard.ASR595X), + ]) + + # apps + target.AppendFixedTargets([ + TargetPart('lighting', app=ASRApp.LIGHT), + ]) + + # modifiers + target.AppendModifier('ota', enable_ota_requestor=True) + target.AppendModifier('shell', chip_build_libshell=True) + target.AppendModifier('no_logging', chip_logging=False) + + return target + + def BuildK32WTarget(): target = BuildTarget('k32w', K32WBuilder) @@ -581,6 +604,7 @@ def BuildOpenIotSdkTargets(): BUILD_TARGETS = [ BuildAmebaTarget(), + BuildASRTarget(), BuildAndroidTarget(), BuildBouffalolabTarget(), Buildcc13x2x7_26x2x7Target(), diff --git a/scripts/build/builders/asr.py b/scripts/build/builders/asr.py new file mode 100644 index 00000000000000..e8ca5aa8b3f715 --- /dev/null +++ b/scripts/build/builders/asr.py @@ -0,0 +1,122 @@ +# Copyright (c) 2023 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 os +from enum import Enum, auto + +from .gn import GnBuilder + + +class ASRApp(Enum): + LIGHT = auto() + + def ExampleName(self): + if self == ASRApp.LIGHT: + return 'lighting-app' + else: + raise Exception('Unknown app type: %r' % self) + + def AppNamePrefix(self): + if self == ASRApp.LIGHT: + return 'chip-asr-lighting-app' + else: + raise Exception('Unknown app type: %r' % self) + + def BuildRoot(self, root): + return os.path.join(root, 'examples', self.ExampleName(), 'asr') + + +class ASRBoard(Enum): + ASR582X = auto() + ASR595X = auto() + + def GetIC(self): + if self == ASRBoard.ASR582X: + return 'asr582x' + elif self == ASRBoard.ASR595X: + return 'asr595x' + else: + raise Exception('Unknown board #: %r' % self) + + +class ASRBuilder(GnBuilder): + + def __init__(self, + root, + runner, + app: ASRApp = ASRApp.LIGHT, + board: ASRBoard = ASRBoard.ASR582X, + chip_build_libshell: bool = False, + chip_logging: bool = True, + enable_factory: bool = False, + enable_ota_requestor: bool = False): + super(ASRBuilder, self).__init__( + root=app.BuildRoot(root), + runner=runner) + + self.board = board + self.app = app + + asr_chip = self.board.GetIC() + self.extra_gn_options = ['asr_ic_family="%s"' % asr_chip] + + if asr_chip == "asr582x": + ASR_ARCH = "arm" + ASR_SDK_ROOT = "//third_party/connectedhomeip/third_party/asr/asr582x" + elif asr_chip == "asr595x": + ASR_ARCH = "riscv" + ASR_SDK_ROOT = "//third_party/connectedhomeip/third_party/asr/asr595x" + self.extra_gn_options.append('target_cpu="%s"' % ASR_ARCH) + + toolchain = os.path.join(root, os.path.split(os.path.realpath(__file__))[0], '../../../config/asr/toolchain') + toolchain = 'custom_toolchain="{}:asrtoolchain"'.format(toolchain) + if toolchain: + self.extra_gn_options.append(toolchain) + + self.extra_gn_options.append('asr_sdk_build_root="%s"' % ASR_SDK_ROOT) + self.extra_gn_options.append('mbedtls_target="%s:asr_build"' % ASR_SDK_ROOT) + + if (asr_chip == "asr582x" + or asr_chip == "asr595x"): + self.extra_gn_options.append('chip_config_network_layer_ble=true') + + if enable_ota_requestor: + self.extra_gn_options.append('chip_enable_ota_requestor=true') + + if chip_build_libshell: + self.extra_gn_options.append('chip_build_libshell=true') + + if chip_logging is False: + self.extra_gn_options.append('chip_logging=false') + + if enable_factory: + self.extra_gn_options.append('chip_use_transitional_commissionable_data_provider=false') + self.extra_gn_options.append('chip_enable_factory_data=true') + + self.extra_gn_options.append('asr_toolchain_root="%s"' % os.environ['ASR_TOOLCHAIN_PATH']) + + def GnBuildArgs(self): + return self.extra_gn_options + + def build_outputs(self): + items = { + '%s.out' % self.app.AppNamePrefix(): + os.path.join(self.output_dir, '%s.out' % + self.app.AppNamePrefix()), + '%s.out.map' % self.app.AppNamePrefix(): + os.path.join(self.output_dir, + '%s.out.map' % self.app.AppNamePrefix()), + } + + return items diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index 63ad58f917a54a..b94855242ce292 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -1,4 +1,5 @@ ameba-amebad-{all-clusters,all-clusters-minimal,light,light-switch,pigweed} +asr-{asr582x,asr595x}-lighting[-ota][-shell][-no_logging] android-{arm,arm64,x86,x64,androidstudio-arm,androidstudio-arm64,androidstudio-x86,androidstudio-x64}-{chip-tool,chip-test,tv-server,tv-casting-app,java-matter-controller}[-no-debug] bouffalolab-{bl602-iot-matter-v1,bl602-iot-dvk-3s,bl602-night-light,xt-zb6-devkit,bl706-iot-dvk,bl706-night-light}-light[-shell][-115200][-rpc][-cdc] cc13x2x7_26x2x7-{all-clusters,all-clusters-minimal,lock,pump,pump-controller,shell}[-ftd][-mtd] diff --git a/scripts/checkout_submodules.py b/scripts/checkout_submodules.py index a401cf8bdbe3e8..22ac0fa754bbe9 100755 --- a/scripts/checkout_submodules.py +++ b/scripts/checkout_submodules.py @@ -27,6 +27,7 @@ ALL_PLATFORMS = set([ 'ameba', 'android', + 'asr', 'bl602', 'bouffalolab', 'cc13xx_26xx', diff --git a/scripts/tools/check_includes_config.py b/scripts/tools/check_includes_config.py index 9f82f3b80017df..e2ec38e223c16a 100644 --- a/scripts/tools/check_includes_config.py +++ b/scripts/tools/check_includes_config.py @@ -52,6 +52,7 @@ '/platform/bouffalolab/BL602', '/platform/webos/', '/platform/mt793x/', + '/platform/ASR/', r'POSIX\.h$', } diff --git a/src/lib/shell/BUILD.gn b/src/lib/shell/BUILD.gn index 67d6b1d69ab5b6..20e87d0027d61f 100644 --- a/src/lib/shell/BUILD.gn +++ b/src/lib/shell/BUILD.gn @@ -113,6 +113,11 @@ static_library("shell") { "MainLoopDefault.cpp", "streamer_openiotsdk.cpp", ] + } else if (chip_device_platform == "asr") { + sources += [ + "MainLoopDefault.cpp", + "streamer_asr.cpp", + ] } else { sources += [ "MainLoopDefault.cpp" ] } diff --git a/src/lib/shell/streamer_asr.cpp b/src/lib/shell/streamer_asr.cpp new file mode 100644 index 00000000000000..ffc48c7df2e317 --- /dev/null +++ b/src/lib/shell/streamer_asr.cpp @@ -0,0 +1,95 @@ +/* + * + * 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. + */ + +#include +#include + +#include "lega_rtos_api.h" +#include "printf_uart.h" +#include +#include +#ifdef CFG_PLF_RV32 +#include "asr_uart.h" +#define duet_uart_set_callback asr_uart_set_callback +#define duet_uart_callback_func asr_uart_callback_func_t +#else +#include "duet_uart.h" +#endif +namespace chip { +namespace Shell { +namespace { + +#define HAL_UART_BUF_QUEUE_BYTES 256 +lega_queue_t hal_uart_buf_queue; + +void shell_handle_uartirq(char ch) +{ + lega_rtos_push_to_queue(&hal_uart_buf_queue, &ch, LEGA_NEVER_TIMEOUT); +} + +int streamer_asr_init(streamer_t * streamer) +{ + (void) streamer; + duet_uart_set_callback(UART1_INDEX, (duet_uart_callback_func)(shell_handle_uartirq)); + lega_rtos_init_queue(&hal_uart_buf_queue, "shell_buffer_queue", sizeof(char), HAL_UART_BUF_QUEUE_BYTES); + return 0; +} + +ssize_t streamer_asr_read(streamer_t * streamer, char * buffer, size_t length) +{ + (void) streamer; + uint16_t i = 0; + uint32_t rx_count = 0; + int32_t ret; + uint8_t * pdata = (uint8_t *) buffer; + for (i = 0; i < (uint16_t) length; i++) + { + ret = lega_rtos_pop_from_queue(&hal_uart_buf_queue, &pdata[i], LEGA_NEVER_TIMEOUT); + + if (!ret) + { + rx_count++; + } + else + { + break; + } + } + return rx_count; +} + +ssize_t streamer_asr_write(streamer_t * streamer, const char * buffer, size_t length) +{ + (void) streamer; + uart_put_buf(buffer, (uint16_t) length); + return length; +} + +static streamer_t streamer_asr = { + .init_cb = streamer_asr_init, + .read_cb = streamer_asr_read, + .write_cb = streamer_asr_write, +}; +} // namespace + +streamer_t * streamer_get(void) +{ + return &streamer_asr; +} + +} // namespace Shell +} // namespace chip diff --git a/src/lwip/BUILD.gn b/src/lwip/BUILD.gn index 8f91f9ec2685da..be41fd44d181e4 100644 --- a/src/lwip/BUILD.gn +++ b/src/lwip/BUILD.gn @@ -34,7 +34,8 @@ assert(lwip_platform == "external" || lwip_platform == "standalone" || lwip_platform == "qpg" || lwip_platform == "mbed" || lwip_platform == "psoc6" || lwip_platform == "cyw30739" || lwip_platform == "bl602" || lwip_platform == "mw320" || - lwip_platform == "bl702" || lwip_platform == "mt793x", + lwip_platform == "bl702" || lwip_platform == "mt793x" || + lwip_platform == "asr", "Unsupported lwIP platform: ${lwip_platform}") if (lwip_platform != "external") { @@ -67,6 +68,8 @@ if (lwip_platform == "cc13xx_26xx") { import("//build_overrides/mw320_sdk.gni") } else if (lwip_platform == "mt793x") { import("//build_overrides/mt793x_sdk.gni") +} else if (lwip_platform == "asr") { + import("//build_overrides/asr.gni") } buildconfig_header("lwip_buildconfig") { @@ -145,6 +148,16 @@ if (current_os == "zephyr" || current_os == "mbed") { public_deps += [ "${bouffalolab_iot_sdk_build_root}/bl602:bl_iot_sdk" ] } + group("all") { + deps = [ ":lwip" ] + } +} else if (lwip_platform == "asr") { + group("lwip") { + public_deps = [ ":lwip_buildconfig" ] + public_configs = [ "${chip_root}/src:includes" ] + public_configs += [ "${asr_sdk_build_root}:asr_sdk_config" ] + } + group("all") { deps = [ ":lwip" ] } diff --git a/src/platform/ASR/ASRConfig.cpp b/src/platform/ASR/ASRConfig.cpp new file mode 100644 index 00000000000000..af8eea30782480 --- /dev/null +++ b/src/platform/ASR/ASRConfig.cpp @@ -0,0 +1,300 @@ +/* + * + * Copyright (c) 2021-2022 Project CHIP Authors + * Copyright (c) 2019-2020 Google LLC. + * 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. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +// *** CAUTION ***: Changing the names or namespaces of these values will *break* existing devices. + +// Namespaces used to store device configuration information. +const char ASRConfig::kConfigNamespace_ChipFactory[] = "chip-factory"; +const char ASRConfig::kConfigNamespace_ChipConfig[] = "chip-config"; +const char ASRConfig::kConfigNamespace_ChipCounters[] = "chip-counters"; + +// Keys stored in the chip-factory namespace +const ASRConfig::Key ASRConfig::kConfigKey_SerialNum = { kConfigNamespace_ChipFactory, "serial-num" }; +const ASRConfig::Key ASRConfig::kConfigKey_MfrDeviceId = { kConfigNamespace_ChipFactory, "device-id" }; +const ASRConfig::Key ASRConfig::kConfigKey_MfrDeviceCert = { kConfigNamespace_ChipFactory, "device-cert" }; +const ASRConfig::Key ASRConfig::kConfigKey_MfrDeviceICACerts = { kConfigNamespace_ChipFactory, "device-ca-certs" }; +const ASRConfig::Key ASRConfig::kConfigKey_MfrDevicePrivateKey = { kConfigNamespace_ChipFactory, "device-key" }; +const ASRConfig::Key ASRConfig::kConfigKey_SoftwareVersion = { kConfigNamespace_ChipFactory, "software-ver" }; +const ASRConfig::Key ASRConfig::kConfigKey_HardwareVersion = { kConfigNamespace_ChipFactory, "hardware-ver" }; +const ASRConfig::Key ASRConfig::kConfigKey_ManufacturingDate = { kConfigNamespace_ChipFactory, "mfg-date" }; +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +const ASRConfig::Key ASRConfig::kConfigKey_SetupPinCode = { kConfigNamespace_ChipFactory, "pin-code" }; +const ASRConfig::Key ASRConfig::kConfigKey_SetupDiscriminator = { kConfigNamespace_ChipFactory, "discriminator" }; +const ASRConfig::Key ASRConfig::kConfigKey_Spake2pIterationCount = { kConfigNamespace_ChipFactory, "iteration-count" }; +const ASRConfig::Key ASRConfig::kConfigKey_Spake2pSalt = { kConfigNamespace_ChipFactory, "salt" }; +const ASRConfig::Key ASRConfig::kConfigKey_Spake2pVerifier = { kConfigNamespace_ChipFactory, "verifier" }; +const ASRConfig::Key ASRConfig::kConfigKey_DACCert = { kConfigNamespace_ChipFactory, "dac-cert" }; +const ASRConfig::Key ASRConfig::kConfigKey_DACPrivateKey = { kConfigNamespace_ChipFactory, "dac-key" }; +const ASRConfig::Key ASRConfig::kConfigKey_DACPublicKey = { kConfigNamespace_ChipFactory, "dac-pub-key" }; +const ASRConfig::Key ASRConfig::kConfigKey_PAICert = { kConfigNamespace_ChipFactory, "pai-cert" }; +const ASRConfig::Key ASRConfig::kConfigKey_CertDeclaration = { kConfigNamespace_ChipFactory, "cert-dclrn" }; +#endif + +// Keys stored in the chip-config namespace +const ASRConfig::Key ASRConfig::kConfigKey_ServiceConfig = { kConfigNamespace_ChipConfig, "service-config" }; +const ASRConfig::Key ASRConfig::kConfigKey_PairedAccountId = { kConfigNamespace_ChipConfig, "account-id" }; +const ASRConfig::Key ASRConfig::kConfigKey_ServiceId = { kConfigNamespace_ChipConfig, "service-id" }; +const ASRConfig::Key ASRConfig::kConfigKey_LastUsedEpochKeyId = { kConfigNamespace_ChipConfig, "last-ek-id" }; +const ASRConfig::Key ASRConfig::kConfigKey_FailSafeArmed = { kConfigNamespace_ChipConfig, "fail-safe-armed" }; +const ASRConfig::Key ASRConfig::kConfigKey_WiFiStationSecType = { kConfigNamespace_ChipConfig, "sta-sec-type" }; +const ASRConfig::Key ASRConfig::kConfigKey_RegulatoryLocation = { kConfigNamespace_ChipConfig, "regulatory-location" }; +const ASRConfig::Key ASRConfig::kConfigKey_CountryCode = { kConfigNamespace_ChipConfig, "country-code" }; +const ASRConfig::Key ASRConfig::kConfigKey_WiFiSSID = { kConfigNamespace_ChipConfig, "wifi-ssid" }; +const ASRConfig::Key ASRConfig::kConfigKey_WiFiPassword = { kConfigNamespace_ChipConfig, "wifi-password" }; +const ASRConfig::Key ASRConfig::kConfigKey_WiFiSecurity = { kConfigNamespace_ChipConfig, "wifi-security" }; +const ASRConfig::Key ASRConfig::kConfigKey_WiFiMode = { kConfigNamespace_ChipConfig, "wifimode" }; +const ASRConfig::Key ASRConfig::kConfigKey_UniqueId = { kConfigNamespace_ChipConfig, "unique-id" }; + +// Keys stored in the Chip-counters namespace +const ASRConfig::Key ASRConfig::kCounterKey_RebootCount = { kConfigNamespace_ChipCounters, "reboot-count" }; +const ASRConfig::Key ASRConfig::kCounterKey_UpTime = { kConfigNamespace_ChipCounters, "up-time" }; +const ASRConfig::Key ASRConfig::kCounterKey_TotalOperationalHours = { kConfigNamespace_ChipCounters, "total-hours" }; + +#define _KVSTORE_MAX_KEY_SIZE 64 + +CHIP_ERROR ASRConfig::ReadConfigValue(Key key, bool & val) +{ + bool in; + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key_str, static_cast(&in), sizeof(bool)); + val = in; + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } + return err; +} + +CHIP_ERROR ASRConfig::ReadConfigValue(Key key, uint32_t & val) +{ + uint32_t in; + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key_str, static_cast(&in), 4); + val = in; + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } + return err; +} + +CHIP_ERROR ASRConfig::ReadConfigValue(Key key, uint64_t & val) +{ + uint64_t in; + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key_str, static_cast(&in), 8); + val = in; + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } + return err; +} + +CHIP_ERROR ASRConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key_str, buf, bufSize, &outLen); + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } + return err; +} + +CHIP_ERROR ASRConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key_str, buf, bufSize, &outLen); + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } + return err; +} + +CHIP_ERROR ASRConfig::WriteConfigValue(Key key, bool val) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + return PersistedStorage::KeyValueStoreMgr().Put(key_str, static_cast(&val), sizeof(bool)); +} + +CHIP_ERROR ASRConfig::WriteConfigValue(Key key, uint32_t val) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + return PersistedStorage::KeyValueStoreMgr().Put(key_str, static_cast(&val), 4); +} + +CHIP_ERROR ASRConfig::WriteConfigValue(Key key, uint64_t val) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + return PersistedStorage::KeyValueStoreMgr().Put(key_str, static_cast(&val), 8); +} + +CHIP_ERROR ASRConfig::WriteConfigValueStr(Key key, const char * str) +{ + size_t size = strlen(str) + 1; + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + return PersistedStorage::KeyValueStoreMgr().Put(key_str, str, size); +} + +CHIP_ERROR ASRConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + return PersistedStorage::KeyValueStoreMgr().Put(key_str, str, strLen); +} + +CHIP_ERROR ASRConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + return PersistedStorage::KeyValueStoreMgr().Put(key_str, static_cast(&data), dataLen); +} + +CHIP_ERROR ASRConfig::ClearConfigValue(Key key) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + return PersistedStorage::KeyValueStoreMgr().Delete(key_str); +} + +bool ASRConfig::ConfigValueExists(Key key) +{ + char key_str[_KVSTORE_MAX_KEY_SIZE] = { 0 }; + char buf[4]; + size_t outLen; + key.to_str(key_str, _KVSTORE_MAX_KEY_SIZE); + if (PersistedStorage::KeyValueStoreMgr().Get(key_str, buf, 4, &outLen) == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + return false; + } + + return true; +} + +#if CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +CHIP_ERROR ASRConfig::ReadFactoryConfigValue(asr_matter_partition_t matter_partition, uint8_t * buf, size_t bufSize, + size_t & outLen) +{ + int32_t ret = 0; + + ret = asr_factory_config_read(matter_partition, buf, (uint32_t) bufSize, (uint32_t *) &outLen); + + if (ret != 0) + ChipLogProgress(DeviceLayer, "asr_factory_config_read: %d failed, ret = %d\n", matter_partition, ret); + + if (ret == 0) + { + return CHIP_NO_ERROR; + } + else + { + outLen = 0; + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } +} + +CHIP_ERROR ASRConfig::ReadFactoryConfigValue(asr_matter_partition_t matter_partition, uint32_t & val) +{ + int32_t ret = 0; + uint8_t buf[4]; + size_t outlen = 0; + + ret = asr_factory_config_read(matter_partition, buf, sizeof(uint32_t), (uint32_t *) &outlen); + + if (outlen > sizeof(uint32_t)) + ret = -1; + + if (ret != 0) + ChipLogProgress(DeviceLayer, "asr_factory_config_read: %d failed, ret = %d\n", matter_partition, ret); + + if (ret == 0) + { + val = *((uint32_t *) buf); + return CHIP_NO_ERROR; + } + else + { + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } +} +#endif +// Clear out keys in config namespace +CHIP_ERROR ASRConfig::FactoryResetConfig(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + const Key * config_keys[] = { &kConfigKey_ServiceConfig, &kConfigKey_PairedAccountId, &kConfigKey_ServiceId, + &kConfigKey_LastUsedEpochKeyId, &kConfigKey_FailSafeArmed, &kConfigKey_WiFiStationSecType, + &kConfigKey_WiFiSSID, &kConfigKey_WiFiPassword, &kConfigKey_WiFiSecurity, + &kConfigKey_WiFiMode, &kConfigKey_SoftwareVersion }; + + for (uint32_t i = 0; i < (sizeof(config_keys) / sizeof(config_keys[0])); i++) + { + err = ClearConfigValue(*config_keys[i]); + // Something unexpected happened + if (err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND && err != CHIP_NO_ERROR) + { + return err; + } + } + + // Erase all key-values including fabric info. + err = PersistedStorage::KeyValueStoreMgrImpl().Erase(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Clear Key-Value Storage failed"); + } + + return CHIP_NO_ERROR; +} + +void ASRConfig::RunConfigUnitTest() {} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/ASRConfig.h b/src/platform/ASR/ASRConfig.h new file mode 100644 index 00000000000000..10895098a1d2df --- /dev/null +++ b/src/platform/ASR/ASRConfig.h @@ -0,0 +1,159 @@ +/* + * + * Copyright (c) 2021-2022 Project CHIP Authors + * Copyright (c) 2019-2020 Google LLC. + * 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. + */ + +/** + * @file + * Utilities for interacting with the the ASR key-value store. + */ + +#pragma once + +// #include + +#include "asr_factory_config.h" +#include + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +/** + * Provides functions and definitions for accessing device configuration information on the ASR. + * + * This class is designed to be mixed-in to concrete implementation classes as a means to + * provide access to configuration information to generic base classes. + */ +class ASRConfig +{ +public: + struct Key; + + // Maximum length of a key name + static constexpr size_t kMaxConfigKeyNameLength = 128; + + // Namespaces used to store device configuration information. + static const char kConfigNamespace_ChipFactory[]; + static const char kConfigNamespace_ChipConfig[]; + static const char kConfigNamespace_ChipCounters[]; + + // Key definitions for well-known keys. + static const Key kConfigKey_SerialNum; + static const Key kConfigKey_UniqueId; + static const Key kConfigKey_MfrDeviceId; + static const Key kConfigKey_MfrDeviceCert; + static const Key kConfigKey_MfrDeviceICACerts; + static const Key kConfigKey_MfrDevicePrivateKey; + static const Key kConfigKey_SoftwareVersion; + static const Key kConfigKey_HardwareVersion; + static const Key kConfigKey_ManufacturingDate; + static const Key kConfigKey_ServiceConfig; + static const Key kConfigKey_PairedAccountId; + static const Key kConfigKey_ServiceId; + static const Key kConfigKey_LastUsedEpochKeyId; + static const Key kConfigKey_FailSafeArmed; + static const Key kConfigKey_WiFiStationSecType; + static const Key kConfigKey_RegulatoryLocation; + static const Key kConfigKey_CountryCode; + static const Key kConfigKey_WiFiSSID; + static const Key kConfigKey_WiFiPassword; + static const Key kConfigKey_WiFiSecurity; + static const Key kConfigKey_WiFiMode; + +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER + static const Key kConfigKey_SetupPinCode; + static const Key kConfigKey_SetupDiscriminator; + static const Key kConfigKey_Spake2pIterationCount; + static const Key kConfigKey_Spake2pSalt; + static const Key kConfigKey_Spake2pVerifier; + static const Key kConfigKey_DACCert; + static const Key kConfigKey_DACPrivateKey; + static const Key kConfigKey_DACPublicKey; + static const Key kConfigKey_PAICert; + static const Key kConfigKey_CertDeclaration; +#endif + // CHIP Counter keys + static const Key kCounterKey_RebootCount; + static const Key kCounterKey_UpTime; + static const Key kCounterKey_TotalOperationalHours; + + // Config value accessors. + static CHIP_ERROR ReadConfigValue(Key key, bool & val); + static CHIP_ERROR ReadConfigValue(Key key, uint32_t & val); + static CHIP_ERROR ReadConfigValue(Key key, uint64_t & val); + static CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen); + static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen); + static CHIP_ERROR WriteConfigValue(Key key, bool val); + static CHIP_ERROR WriteConfigValue(Key key, uint32_t val); + static CHIP_ERROR WriteConfigValue(Key key, uint64_t val); + static CHIP_ERROR WriteConfigValueStr(Key key, const char * str); + static CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen); + static CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen); + static CHIP_ERROR ClearConfigValue(Key key); + static bool ConfigValueExists(Key key); +#if CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER + static CHIP_ERROR ReadFactoryConfigValue(asr_matter_partition_t matter_partition, uint8_t * buf, size_t bufSize, + size_t & outLen); + static CHIP_ERROR ReadFactoryConfigValue(asr_matter_partition_t matter_partition, uint32_t & val); +#endif + static CHIP_ERROR FactoryResetConfig(void); + + static void RunConfigUnitTest(void); +}; + +struct ASRConfig::Key +{ + const char * Namespace; + const char * Name; + + CHIP_ERROR to_str(char * buf, size_t buf_size) const; + size_t len() const; + bool operator==(const Key & other) const; +}; + +inline CHIP_ERROR ASRConfig::Key::to_str(char * buf, size_t buf_size) const +{ + if (buf_size < len() + 1) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + + strcpy(buf, Namespace); + strcat(buf, ";"); + strcat(buf, Name); + + return CHIP_NO_ERROR; +} + +// Length of key str (not including terminating null char) +inline size_t ASRConfig::Key::len() const +{ + // + 1 for separating ';' + size_t out_size = strlen(Namespace) + strlen(Name) + 1; + return out_size; +} + +inline bool ASRConfig::Key::operator==(const Key & other) const +{ + return strcmp(Namespace, other.Namespace) == 0 && strcmp(Name, other.Name) == 0; +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/ASRFactoryDataProvider.cpp b/src/platform/ASR/ASRFactoryDataProvider.cpp new file mode 100644 index 00000000000000..e6203980297af9 --- /dev/null +++ b/src/platform/ASR/ASRFactoryDataProvider.cpp @@ -0,0 +1,481 @@ +/* + * + * 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 +#include +#include + +namespace chip { +namespace DeviceLayer { + +using namespace chip::Credentials; +using namespace chip::DeviceLayer::Internal; + +namespace { +static constexpr uint32_t kDACPrivateKeySize = 32; +static constexpr uint32_t kDACPublicKeySize = 65; + +CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) +{ + Crypto::P256SerializedKeypair serializedKeypair; + ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); + memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); + memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); + return keypair.Deserialize(serializedKeypair); +} +} // namespace + +CHIP_ERROR ASRFactoryDataProvider::Init() +{ + CHIP_ERROR err = CHIP_NO_ERROR; +#if CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER + uint8_t ret = asr_factory_check(); + if (ret != 0) + { + err = CHIP_ERROR_INTERNAL; + ChipLogError(DeviceLayer, "The hash of factory bin is not correct."); + } +#endif + return err; +} + +CHIP_ERROR ASRFactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator) +{ + uint32_t setupDiscriminator32; +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR + setupDiscriminator32 = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR; +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR +#else + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_DISCRIMINATOR_PARTITION, setupDiscriminator32)); +#endif + VerifyOrReturnLogError(setupDiscriminator32 <= kMaxDiscriminatorValue, CHIP_ERROR_INVALID_ARGUMENT); + setupDiscriminator = static_cast(setupDiscriminator32); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount) +{ +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT + iterationCount = CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT; + return CHIP_NO_ERROR; +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT +#else + return ASRConfig::ReadFactoryConfigValue(ASR_ITERATION_COUNT_PARTITION, iterationCount); +#endif +} + +CHIP_ERROR ASRFactoryDataProvider::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; +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT) + 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); +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT) +#else + err = ASRConfig::ReadFactoryConfigValue(ASR_SALT_PARTITION, reinterpret_cast(saltB64), kSpake2pSalt_MaxBase64Len, + saltB64Len); +#endif + ReturnErrorOnFailure(err); + + size_t saltLen = chip::Base64Decode32(saltB64, saltB64Len, reinterpret_cast(saltB64)); + ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + + memcpy(saltBuf.data(), saltB64, saltLen); + saltBuf.reduce_size(saltLen); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::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; +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER) + 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); +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER) +#else + err = ASRConfig::ReadFactoryConfigValue(ASR_VERIFIER_PARTITION, reinterpret_cast(verifierB64), + kSpake2pSerializedVerifier_MaxBase64Len, verifierB64Len); +#endif + 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; +} + +#define USE_EXAMPLES_DAC // VID:0xFFF1 PID:0x8001 + +#if CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#undef USE_EXAMPLES_DAC +#endif + +CHIP_ERROR ASRFactoryDataProvider::GetCertificationDeclaration(MutableByteSpan & outBuffer) +{ +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#ifdef USE_EXAMPLES_DAC + //-> format_version = 1 + //-> vendor_id = 0xFFF1 + //-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B, + // 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A, + // 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, + // 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038, + // 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047, + // 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056, + // 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ] + //-> device_type_id = 0x0016 + //-> certificate_id = "ZIG20142ZB330003-24" + //-> security_level = 0 + //-> security_information = 0 + //-> version_number = 0x2694 + //-> certification_type = 0 + //-> dac_origin_vendor_id is not present + //-> dac_origin_product_id is not present + const uint8_t kCdForAllExamples[541] = { + 0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30, + 0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x62, + 0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80, + 0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, 0x07, 0x80, 0x05, 0x08, + 0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, 0x80, 0x05, 0x0e, 0x80, 0x05, + 0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, 0x05, 0x14, 0x80, 0x05, 0x15, 0x80, + 0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c, + 0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05, + 0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80, + 0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30, + 0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05, + 0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80, + 0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44, + 0x80, 0x05, 0x45, 0x80, 0x05, 0x46, 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05, + 0x4b, 0x80, 0x05, 0x4c, 0x80, 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80, + 0x05, 0x52, 0x80, 0x05, 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58, + 0x80, 0x05, 0x59, 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05, + 0x5f, 0x80, 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04, + 0x13, 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34, + 0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01, + 0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04, + 0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, 0xd1, 0xf4, 0x7a, 0x7d, + 0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, 0x89, 0xde, 0x31, 0x92, 0xe6, + 0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97, + 0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a, + 0x7c, + }; + return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, outBuffer); +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif +#else + size_t certSize; + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_CERT_DCLRN_PARTITION, outBuffer.data(), outBuffer.size(), certSize)); + outBuffer.reduce_size(certSize); + return CHIP_NO_ERROR; +#endif +} + +CHIP_ERROR ASRFactoryDataProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) +{ + // We do not provide any FirmwareInformation. + out_firmware_info_buffer.reduce_size(0); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & outBuffer) +{ + size_t certSize; +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#ifdef USE_EXAMPLES_DAC + const uint8_t kDacCert[491] = { + 0x30, 0x82, 0x01, 0xe7, 0x30, 0x82, 0x01, 0x8e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x69, 0xcd, 0xf1, 0x0d, 0xe9, + 0xe5, 0x4e, 0xd1, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3d, 0x31, 0x25, 0x30, + 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x44, 0x65, 0x76, 0x20, 0x50, + 0x41, 0x49, 0x20, 0x30, 0x78, 0x46, 0x46, 0x46, 0x31, 0x20, 0x6e, 0x6f, 0x20, 0x50, 0x49, 0x44, 0x31, 0x14, 0x30, 0x12, + 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, 0x04, 0x46, 0x46, 0x46, 0x31, 0x30, 0x20, + 0x17, 0x0d, 0x32, 0x32, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, + 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x44, 0x65, 0x76, 0x20, 0x44, 0x41, 0x43, 0x20, + 0x30, 0x78, 0x46, 0x46, 0x46, 0x31, 0x2f, 0x30, 0x78, 0x38, 0x30, 0x30, 0x31, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, + 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, 0x04, 0x46, 0x46, 0x46, 0x31, 0x31, 0x14, 0x30, 0x12, 0x06, + 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x02, 0x0c, 0x04, 0x38, 0x30, 0x30, 0x31, 0x30, 0x59, 0x30, + 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + 0x03, 0x42, 0x00, 0x04, 0x46, 0x3a, 0xc6, 0x93, 0x42, 0x91, 0x0a, 0x0e, 0x55, 0x88, 0xfc, 0x6f, 0xf5, 0x6b, 0xb6, 0x3e, + 0x62, 0xec, 0xce, 0xcb, 0x14, 0x8f, 0x7d, 0x4e, 0xb0, 0x3e, 0xe5, 0x52, 0x60, 0x14, 0x15, 0x76, 0x7d, 0x16, 0xa5, 0xc6, + 0x63, 0xf7, 0x93, 0xe4, 0x91, 0x23, 0x26, 0x0b, 0x82, 0x97, 0xa7, 0xcd, 0x7e, 0x7c, 0xfc, 0x7b, 0x31, 0x6b, 0x39, 0xd9, + 0x8e, 0x90, 0xd2, 0x93, 0x77, 0x73, 0x8e, 0x82, 0xa3, 0x60, 0x30, 0x5e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, + 0x07, 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x88, 0xdd, 0xe7, 0xb3, 0x00, 0x38, 0x29, + 0x32, 0xcf, 0xf7, 0x34, 0xc0, 0x46, 0x24, 0x81, 0x0f, 0x44, 0x16, 0x8a, 0x6f, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x63, 0x54, 0x0e, 0x47, 0xf6, 0x4b, 0x1c, 0x38, 0xd1, 0x38, 0x84, 0xa4, 0x62, 0xd1, + 0x6c, 0x19, 0x5d, 0x8f, 0xfb, 0x3c, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, + 0x00, 0x30, 0x44, 0x02, 0x20, 0x01, 0x27, 0xa2, 0x7b, 0x4b, 0x44, 0x61, 0x0e, 0xe2, 0xfc, 0xdc, 0x4d, 0x2b, 0x78, 0x85, + 0x56, 0x36, 0x60, 0xbc, 0x0f, 0x76, 0xf1, 0x72, 0x19, 0xed, 0x6a, 0x08, 0xdf, 0xb2, 0xb3, 0xc1, 0xcd, 0x02, 0x20, 0x6b, + 0x59, 0xe0, 0xaf, 0x45, 0xf3, 0xeb, 0x2a, 0x85, 0xb9, 0x19, 0xd3, 0x57, 0x31, 0x52, 0x8c, 0x60, 0x28, 0xc4, 0x15, 0x23, + 0x95, 0x45, 0xe1, 0x08, 0xe4, 0xe5, 0x4e, 0x70, 0x97, 0x13, 0x53, + }; + return CopySpanToMutableSpan(ByteSpan{ kDacCert }, outBuffer); +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif +#else + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_DAC_CERT_PARTITION, outBuffer.data(), outBuffer.size(), certSize)); +#endif + outBuffer.reduce_size(certSize); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) +{ + size_t certSize; +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#ifdef USE_EXAMPLES_DAC + const uint8_t kPaiCert[463] = { + 0x30, 0x82, 0x01, 0xcb, 0x30, 0x82, 0x01, 0x71, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x56, 0xad, 0x82, 0x22, 0xad, + 0x94, 0x5b, 0x64, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x30, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, + 0x50, 0x41, 0x41, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, + 0x04, 0x46, 0x46, 0x46, 0x31, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, + 0x3d, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x44, + 0x65, 0x76, 0x20, 0x50, 0x41, 0x49, 0x20, 0x30, 0x78, 0x46, 0x46, 0x46, 0x31, 0x20, 0x6e, 0x6f, 0x20, 0x50, 0x49, 0x44, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, 0x04, 0x46, 0x46, + 0x46, 0x31, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x41, 0x9a, 0x93, 0x15, 0xc2, 0x17, 0x3e, 0x0c, 0x8c, 0x87, 0x6d, + 0x03, 0xcc, 0xfc, 0x94, 0x48, 0x52, 0x64, 0x7f, 0x7f, 0xec, 0x5e, 0x50, 0x82, 0xf4, 0x05, 0x99, 0x28, 0xec, 0xa8, 0x94, + 0xc5, 0x94, 0x15, 0x13, 0x09, 0xac, 0x63, 0x1e, 0x4c, 0xb0, 0x33, 0x92, 0xaf, 0x68, 0x4b, 0x0b, 0xaf, 0xb7, 0xe6, 0x5b, + 0x3b, 0x81, 0x62, 0xc2, 0xf5, 0x2b, 0xf9, 0x31, 0xb8, 0xe7, 0x7a, 0xaa, 0x82, 0xa3, 0x66, 0x30, 0x64, 0x30, 0x12, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0x63, 0x54, 0x0e, 0x47, 0xf6, 0x4b, 0x1c, 0x38, 0xd1, 0x38, 0x84, 0xa4, 0x62, 0xd1, 0x6c, 0x19, + 0x5d, 0x8f, 0xfb, 0x3c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x6a, 0xfd, 0x22, + 0x77, 0x1f, 0x51, 0x1f, 0xec, 0xbf, 0x16, 0x41, 0x97, 0x67, 0x10, 0xdc, 0xdc, 0x31, 0xa1, 0x71, 0x7e, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xb2, 0xef, 0x27, + 0xf4, 0x9a, 0xe9, 0xb5, 0x0f, 0xb9, 0x1e, 0xea, 0xc9, 0x4c, 0x4d, 0x0b, 0xdb, 0xb8, 0xd7, 0x92, 0x9c, 0x6c, 0xb8, 0x8f, + 0xac, 0xe5, 0x29, 0x36, 0x8d, 0x12, 0x05, 0x4c, 0x0c, 0x02, 0x20, 0x65, 0x5d, 0xc9, 0x2b, 0x86, 0xbd, 0x90, 0x98, 0x82, + 0xa6, 0xc6, 0x21, 0x77, 0xb8, 0x25, 0xd7, 0xd0, 0x5e, 0xdb, 0xe7, 0xc2, 0x2f, 0x9f, 0xea, 0x71, 0x22, 0x0e, 0x7e, 0xa7, + 0x03, 0xf8, 0x91, + }; + return CopySpanToMutableSpan(ByteSpan{ kPaiCert }, outBuffer); +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif +#else + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_PAI_CERT_PARTITION, outBuffer.data(), outBuffer.size(), certSize)); +#endif + outBuffer.reduce_size(certSize); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) +{ + Crypto::P256ECDSASignature signature; + Crypto::P256Keypair keypair; + + VerifyOrReturnError(IsSpanUsable(outSignBuffer), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsSpanUsable(messageToSign), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); + +#if !CONFIG_ENABLE_ASR_FACTORY_DATA_PROVIDER +#ifdef USE_EXAMPLES_DAC + const uint8_t kDacPublicKey[65] = { + 0x04, 0x46, 0x3a, 0xc6, 0x93, 0x42, 0x91, 0x0a, 0x0e, 0x55, 0x88, 0xfc, 0x6f, 0xf5, 0x6b, 0xb6, 0x3e, + 0x62, 0xec, 0xce, 0xcb, 0x14, 0x8f, 0x7d, 0x4e, 0xb0, 0x3e, 0xe5, 0x52, 0x60, 0x14, 0x15, 0x76, 0x7d, + 0x16, 0xa5, 0xc6, 0x63, 0xf7, 0x93, 0xe4, 0x91, 0x23, 0x26, 0x0b, 0x82, 0x97, 0xa7, 0xcd, 0x7e, 0x7c, + 0xfc, 0x7b, 0x31, 0x6b, 0x39, 0xd9, 0x8e, 0x90, 0xd2, 0x93, 0x77, 0x73, 0x8e, 0x82, + }; + const uint8_t kDacPrivateKey[32] = { + 0xaa, 0xb6, 0x00, 0xae, 0x8a, 0xe8, 0xaa, 0xb7, 0xd7, 0x36, 0x27, 0xc2, 0x17, 0xb7, 0xc2, 0x04, + 0x70, 0x9c, 0xa6, 0x94, 0x6a, 0xf5, 0xf2, 0xf7, 0x53, 0x08, 0x33, 0xa5, 0x2b, 0x44, 0xfb, 0xff, + }; + ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan{ kDacPrivateKey }, ByteSpan{ kDacPublicKey }, keypair)); +#else + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; +#endif +#else + uint8_t privKeyBuf[kDACPrivateKeySize]; + uint8_t pubKeyBuf[kDACPublicKeySize]; + size_t privKeyLen = sizeof(privKeyBuf); + size_t pubKeyLen = sizeof(pubKeyBuf); + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_DAC_KEY_PARTITION, privKeyBuf, privKeyLen, privKeyLen)); + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_DAC_PUB_KEY_PARTITION, pubKeyBuf, pubKeyLen, pubKeyLen)); + ReturnErrorOnFailure(LoadKeypairFromRaw(ByteSpan(privKeyBuf, privKeyLen), ByteSpan(pubKeyBuf, pubKeyLen), keypair)); +#endif + + ReturnErrorOnFailure(keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature)); + + return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); +} + +CHIP_ERROR ASRFactoryDataProvider::GetVendorName(char * buf, size_t bufSize) +{ +#if !CONFIG_ENABLE_ASR_FACTORY_DEVICE_INFO_PROVIDER + ReturnErrorCodeIf(bufSize < sizeof(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME), CHIP_ERROR_BUFFER_TOO_SMALL); + strcpy(buf, CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME); +#else +#define BUFFER_MAX_SIZE 32 + uint8_t buffer[BUFFER_MAX_SIZE + 1] = { 0 }; + size_t buffer_len = BUFFER_MAX_SIZE + 1; + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_VENDOR_NAME_PARTITION, buffer, buffer_len, buffer_len)); + ReturnErrorCodeIf(bufSize < buffer_len, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(buf, buffer, buffer_len); + buf[buffer_len] = 0; +#endif + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetVendorId(uint16_t & vendorId) +{ +#if !CONFIG_ENABLE_ASR_FACTORY_DEVICE_INFO_PROVIDER + vendorId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID); +#else + uint32_t vendorId32; + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_VENDOR_ID_PARTITION, vendorId32)); + vendorId = static_cast(vendorId32); +#endif + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetProductName(char * buf, size_t bufSize) +{ +#if !CONFIG_ENABLE_ASR_FACTORY_DEVICE_INFO_PROVIDER + ReturnErrorCodeIf(bufSize < sizeof(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME), CHIP_ERROR_BUFFER_TOO_SMALL); + strcpy(buf, CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME); +#else +#define BUFFER_MAX_SIZE 32 + uint8_t buffer[BUFFER_MAX_SIZE + 1] = { 0 }; + size_t buffer_len = BUFFER_MAX_SIZE + 1; + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_PRODUCT_NAME_PARTITION, buffer, buffer_len, buffer_len)); + ReturnErrorCodeIf(bufSize < buffer_len, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(buf, buffer, buffer_len); + buf[buffer_len] = 0; +#endif + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetProductId(uint16_t & productId) +{ +#if !CONFIG_ENABLE_ASR_FACTORY_DEVICE_INFO_PROVIDER + productId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID); +#else + uint32_t productId32; + ReturnErrorOnFailure(ASRConfig::ReadFactoryConfigValue(ASR_PRODUCT_ID_PARTITION, productId32)); + productId = static_cast(productId32); +#endif + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetPartNumber(char * buf, size_t bufSize) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR ASRFactoryDataProvider::GetProductURL(char * buf, size_t bufSize) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR ASRFactoryDataProvider::GetProductLabel(char * buf, size_t bufSize) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR ASRFactoryDataProvider::GetSerialNumber(char * buf, size_t bufSize) +{ + ChipError err = CHIP_NO_ERROR; + + size_t serialNumLen = 0; // without counting null-terminator + +#ifdef CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER + if (CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER[0] != 0) + { + ReturnErrorCodeIf(sizeof(CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER) > bufSize, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(buf, CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER, sizeof(CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER)); + serialNumLen = sizeof(CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER) - 1; + err = CHIP_NO_ERROR; + } +#endif // CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER + + ReturnErrorCodeIf(serialNumLen >= bufSize, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(buf[serialNumLen] != 0, CHIP_ERROR_INVALID_STRING_LENGTH); + + return err; +} + +CHIP_ERROR ASRFactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR ASRFactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR ASRFactoryDataProvider::GetHardwareVersionString(char * buf, size_t bufSize) +{ + ReturnErrorCodeIf(bufSize < sizeof(CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING), CHIP_ERROR_BUFFER_TOO_SMALL); + strcpy(buf, CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRFactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) +{ + ChipError err = CHIP_ERROR_WRONG_KEY_TYPE; +#if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) + static_assert(ConfigurationManager::kRotatingDeviceIDUniqueIDLength >= ConfigurationManager::kMinRotatingDeviceIDUniqueIDLength, + "Length of unique ID for rotating device ID is smaller than minimum."); + constexpr uint8_t uniqueId[] = CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID; + + ReturnErrorCodeIf(sizeof(uniqueId) > uniqueIdSpan.size(), CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorCodeIf(sizeof(uniqueId) != ConfigurationManager::kRotatingDeviceIDUniqueIDLength, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(uniqueIdSpan.data(), uniqueId, sizeof(uniqueId)); + uniqueIdSpan.reduce_size(sizeof(uniqueId)); + return CHIP_NO_ERROR; +#endif + return err; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/ASRFactoryDataProvider.h b/src/platform/ASR/ASRFactoryDataProvider.h new file mode 100644 index 00000000000000..87e15e034414e0 --- /dev/null +++ b/src/platform/ASR/ASRFactoryDataProvider.h @@ -0,0 +1,95 @@ +/* + * + * 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 +#include + +namespace chip { +namespace DeviceLayer { + +/** + * @brief This class provides Commissionable data and Device Attestation Credentials. + */ + +class ASRFactoryDataProvider : public CommissionableDataProvider, + public Credentials::DeviceAttestationCredentialsProvider, + public Internal::GenericDeviceInstanceInfoProvider +{ +public: + ASRFactoryDataProvider() : + CommissionableDataProvider(), Credentials::DeviceAttestationCredentialsProvider(), + Internal::GenericDeviceInstanceInfoProvider(ConfigurationManagerImpl::GetDefaultInstance()) + {} + + CHIP_ERROR Init(); + + // ===== 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 DeviceAttestationCredentialsProvider + CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override; + + CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override; + + CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override; + + CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override; + + CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override; + + // ===== Members functions that implement the DeviceInstanceInfoProvider + 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 GetPartNumber(char * buf, size_t bufSize) override; + + CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override; + + CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) 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; + + CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override; + + CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override; +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/ASROTAImageProcessor.cpp b/src/platform/ASR/ASROTAImageProcessor.cpp new file mode 100644 index 00000000000000..beb7e6e4d2e534 --- /dev/null +++ b/src/platform/ASR/ASROTAImageProcessor.cpp @@ -0,0 +1,271 @@ +/* + * + * 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 "ASROTAImageProcessor.h" +#include +#include + +/// No error, operation OK +#define LEGA_OTA_OK 0L + +namespace chip { + +CHIP_ERROR ASROTAImageProcessor::PrepareDownload() +{ + DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASROTAImageProcessor::Finalize() +{ + DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} +CHIP_ERROR ASROTAImageProcessor::Apply() +{ + DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASROTAImageProcessor::Abort() +{ + DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASROTAImageProcessor::ProcessBlock(ByteSpan & block) +{ + if ((block.data() == nullptr) || block.empty()) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Store block data for HandleProcessBlock to access + CHIP_ERROR err = SetBlock(block); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format()); + } + + DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +bool ASROTAImageProcessor::IsFirstImageRun() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return false; + } + + return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying; +} + +CHIP_ERROR ASROTAImageProcessor::ConfirmCurrentImage() +{ + OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + uint32_t currentVersion; + uint32_t targetVersion = requestor->GetTargetVersion(); + ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion)); + if (currentVersion != targetVersion) + { + ChipLogError(SoftwareUpdate, "Current software version = %" PRIu32 ", expected software version = %" PRIu32, currentVersion, + targetVersion); + return CHIP_ERROR_INCORRECT_STATE; + } + + return CHIP_NO_ERROR; +} + +void ASROTAImageProcessor::HandlePrepareDownload(intptr_t context) +{ + int32_t err = LEGA_OTA_OK; + auto * imageProcessor = reinterpret_cast(context); + + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + else if (imageProcessor->mDownloader == nullptr) + { + ChipLogError(SoftwareUpdate, "mDownloader is null"); + return; + } + + imageProcessor->ota_boot_para.off_bp = 0; + err = lega_ota_init(&imageProcessor->ota_boot_para); + + imageProcessor->mWriteOffset = nullptr; + + imageProcessor->mHeaderParser.Init(); + + imageProcessor->mDownloader->OnPreparedForDownload(err == LEGA_OTA_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL); +} + +void ASROTAImageProcessor::HandleFinalize(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + return; + } + + imageProcessor->ReleaseBlock(); + + ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully"); +} + +void ASROTAImageProcessor::HandleApply(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + + ChipLogProgress(SoftwareUpdate, "ASROTAImageProcessor::HandleApply()"); + + imageProcessor->ota_boot_para.res_type = LEGA_OTA_FINISH; + lega_ota_set_boot(&imageProcessor->ota_boot_para); + + // reboot(); +} + +void ASROTAImageProcessor::HandleAbort(intptr_t context) +{ + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + return; + } + + // Not clearing the image storage area as it is done during each write + imageProcessor->ReleaseBlock(); +} + +void ASROTAImageProcessor::HandleProcessBlock(intptr_t context) +{ + uint32_t err = LEGA_OTA_OK; + auto * imageProcessor = reinterpret_cast(context); + if (imageProcessor == nullptr) + { + ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + return; + } + else if (imageProcessor->mDownloader == nullptr) + { + ChipLogError(SoftwareUpdate, "mDownloader is null"); + return; + } + + ByteSpan block = imageProcessor->mBlock; + CHIP_ERROR chip_error = imageProcessor->ProcessHeader(block); + + if (chip_error != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Matter image header parser error %s", chip::ErrorStr(chip_error)); + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INVALID_FILE_IDENTIFIER); + return; + } + + err = lega_ota_write(imageProcessor->mWriteOffset, (char *) (block.data()), block.size()); + + if (err) + { + ChipLogError(SoftwareUpdate, "HandleProcessBlock ERROR %ld", err); + + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); + return; + } + + imageProcessor->mParams.downloadedBytes += block.size(); + imageProcessor->mDownloader->FetchNextData(); +} + +CHIP_ERROR ASROTAImageProcessor::ProcessHeader(ByteSpan & block) +{ + if (mHeaderParser.IsInitialized()) + { + OTAImageHeader header; + CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header); + + // Needs more data to decode the header + ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); + ReturnErrorOnFailure(error); + + // SL TODO -- store version somewhere + ChipLogProgress(SoftwareUpdate, "Image Header software version: %ld payload size: %lu", header.mSoftwareVersion, + (long unsigned int) header.mPayloadSize); + mParams.totalFileBytes = header.mPayloadSize; + mHeaderParser.Clear(); + } + return CHIP_NO_ERROR; +} + +// Store block data for HandleProcessBlock to access +CHIP_ERROR ASROTAImageProcessor::SetBlock(ByteSpan & block) +{ + if ((block.data() == nullptr) || block.empty()) + { + return CHIP_NO_ERROR; + } + + // Allocate memory for block data if we don't have enough already + if (mBlock.size() < block.size()) + { + ReleaseBlock(); + + mBlock = MutableByteSpan(static_cast(chip::Platform::MemoryAlloc(block.size())), block.size()); + if (mBlock.data() == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + } + + // Store the actual block data + CHIP_ERROR err = CopySpanToMutableSpan(block, mBlock); + if (err != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Cannot copy block data: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASROTAImageProcessor::ReleaseBlock() +{ + if (mBlock.data() != nullptr) + { + chip::Platform::MemoryFree(mBlock.data()); + } + + mBlock = MutableByteSpan(); + return CHIP_NO_ERROR; +} + +} // namespace chip diff --git a/src/platform/ASR/ASROTAImageProcessor.h b/src/platform/ASR/ASROTAImageProcessor.h new file mode 100755 index 00000000000000..5b08ef90917ad1 --- /dev/null +++ b/src/platform/ASR/ASROTAImageProcessor.h @@ -0,0 +1,72 @@ +/* + * + * 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 +extern "C" { +#include "ota_port.h" +} + +namespace chip { + +class ASROTAImageProcessor : public OTAImageProcessorInterface +{ +public: + //////////// OTAImageProcessorInterface Implementation /////////////// + CHIP_ERROR PrepareDownload() override; + CHIP_ERROR Finalize() override; + CHIP_ERROR Apply() override; + CHIP_ERROR Abort() override; + CHIP_ERROR ProcessBlock(ByteSpan & block) override; + bool IsFirstImageRun() override; + CHIP_ERROR ConfirmCurrentImage() override; + + void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; } + void SetOTAImageFile(const char * imageFile) { mImageFile = imageFile; } + +private: + //////////// Actual handlers for the OTAImageProcessorInterface /////////////// + static void HandlePrepareDownload(intptr_t context); + static void HandleFinalize(intptr_t context); + static void HandleApply(intptr_t context); + static void HandleAbort(intptr_t context); + static void HandleProcessBlock(intptr_t context); + CHIP_ERROR ProcessHeader(ByteSpan & block); + + /** + * Called to allocate memory for mBlock if necessary and set it to block + */ + CHIP_ERROR SetBlock(ByteSpan & block); + + /** + * Called to release allocated memory for mBlock + */ + CHIP_ERROR ReleaseBlock(); + lega_ota_boot_param_t ota_boot_para; + int * mWriteOffset; + MutableByteSpan mBlock; + OTADownloader * mDownloader; + OTAImageHeaderParser mHeaderParser; + const char * mImageFile = nullptr; +}; + +} // namespace chip diff --git a/src/platform/ASR/ASRUtils.cpp b/src/platform/ASR/ASRUtils.cpp new file mode 100644 index 00000000000000..cecf87f2e20d45 --- /dev/null +++ b/src/platform/ASR/ASRUtils.cpp @@ -0,0 +1,305 @@ +/* + * + * Copyright (c) 2021 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. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include "lega_wlan_api.h" +void lega_wlan_clear_pmk(void); +#ifdef __cplusplus +} +#endif + +using namespace ::chip::DeviceLayer::Internal; +using chip::DeviceLayer::Internal::DeviceNetworkInfo; + +namespace { +lega_wlan_wifi_conf wifi_conf; +} // namespace +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP +CHIP_ERROR ASRUtils::IsAPEnabled(bool & apEnabled) +{ + if (lega_wlan_get_wifi_mode() == SOFTAP) + { + apEnabled = true; + } + else + { + apEnabled = false; + } + return CHIP_NO_ERROR; +} +#endif +CHIP_ERROR ASRUtils::IsStationEnabled(bool & staEnabled) +{ + if (lega_wlan_get_wifi_mode() == STA) + { + staEnabled = true; + } + else + { + staEnabled = false; + } + return CHIP_NO_ERROR; +} + +bool ASRUtils::IsStationProvisioned(void) +{ + lega_wlan_wifi_conf stationConfig; + bool stationConnected; + Internal::ASRUtils::IsStationConnected(stationConnected); + return (asr_wifi_get_config(&stationConfig) == CHIP_NO_ERROR && stationConfig.ssid_len != 0) || stationConnected; +} + +static bool is_sta_connected = false; + +CHIP_ERROR ASRUtils::IsStationConnected(bool & connected) +{ + connected = is_sta_connected; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRUtils::SetStationConnected(bool connected) +{ + is_sta_connected = connected; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRUtils::EnableStationMode(void) +{ + int curmode = lega_wlan_get_wifi_mode(); + + if (curmode == STA) + { + ChipLogError(DeviceLayer, "EnableStationMode, STA already"); + } + else + { + ChipLogProgress(DeviceLayer, "Changing ASR WiFi mode to STA"); + lega_wlan_init_type_t conf; + + memset(&conf, 0, sizeof(lega_wlan_init_type_t)); + conf.wifi_mode = STA; + conf.dhcp_mode = WLAN_DHCP_CLIENT; + + // before wlan open with sta mode, make sure the wlan is closed. + lega_wlan_close(); + + if (lega_wlan_open(&conf) != 0) + { + ChipLogError(DeviceLayer, "lega_wlan_open() failed"); + return CHIP_ERROR_INTERNAL; + } + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRUtils::GetWiFiSSID(char * buf, size_t bufSize) +{ + size_t num = 0; + return ASRConfig::ReadConfigValueStr(ASRConfig::kConfigKey_WiFiSSID, buf, bufSize, num); +} + +CHIP_ERROR ASRUtils::StoreWiFiSSID(char * buf, size_t size) +{ + return ASRConfig::WriteConfigValueStr(ASRConfig::kConfigKey_WiFiSSID, buf, size); +} + +CHIP_ERROR ASRUtils::GetWiFiPassword(char * buf, size_t bufSize) +{ + size_t num = 0; + return ASRConfig::ReadConfigValueStr(ASRConfig::kConfigKey_WiFiPassword, buf, bufSize, num); +} + +CHIP_ERROR ASRUtils::StoreWiFiPassword(char * buf, size_t size) +{ + return ASRConfig::WriteConfigValueStr(ASRConfig::kConfigKey_WiFiPassword, buf, size); +} + +CHIP_ERROR ASRUtils::GetWiFiSecurityCode(uint32_t & security) +{ + return ASRConfig::ReadConfigValue(ASRConfig::kConfigKey_WiFiSecurity, security); +} + +CHIP_ERROR ASRUtils::StoreWiFiSecurityCode(uint32_t security) +{ + return ASRConfig::WriteConfigValue(ASRConfig::kConfigKey_WiFiSecurity, security); +} + +CHIP_ERROR ASRUtils::wifi_get_mode(uint32_t & mode) +{ + return ASRConfig::ReadConfigValue(ASRConfig::kConfigKey_WiFiMode, mode); +} + +CHIP_ERROR ASRUtils::wifi_set_mode(uint32_t mode) +{ + return ASRConfig::WriteConfigValue(ASRConfig::kConfigKey_WiFiMode, mode); +} + +CHIP_ERROR ASRUtils::asr_wifi_set_config(lega_wlan_wifi_conf * conf) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + /* Store Wi-Fi Configurations in Storage */ + err = StoreWiFiSSID((char *) conf->wifi_ssid, conf->ssid_len + 1); + SuccessOrExit(err); + + err = StoreWiFiPassword((char *) conf->wifi_key, conf->key_len + 1); + SuccessOrExit(err); + + err = StoreWiFiSecurityCode(conf->security); + SuccessOrExit(err); + + memcpy(&wifi_conf, conf, sizeof(lega_wlan_wifi_conf)); + +exit: + return err; +} + +CHIP_ERROR ASRUtils::asr_wifi_get_config(lega_wlan_wifi_conf * conf) +{ + uint32_t code = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + + if (ASRConfig::ConfigValueExists(ASRConfig::kConfigKey_WiFiSSID) && + ASRConfig::ConfigValueExists(ASRConfig::kConfigKey_WiFiPassword) && + ASRConfig::ConfigValueExists(ASRConfig::kConfigKey_WiFiSecurity)) + { + /* Retrieve Wi-Fi Configurations from Storage */ + err = GetWiFiSSID((char *) conf->wifi_ssid, sizeof(conf->wifi_ssid)); + SuccessOrExit(err); + + err = GetWiFiPassword((char *) conf->wifi_key, sizeof(conf->wifi_key)); + SuccessOrExit(err); + + err = GetWiFiSecurityCode(code); + + conf->ssid_len = strlen((char *) conf->wifi_ssid); + + conf->key_len = strlen((char *) conf->wifi_key); + + SuccessOrExit(err); + conf->security = static_cast(code); + } + else + { + return CHIP_ERROR_KEY_NOT_FOUND; + } + +exit: + return err; +} + +CHIP_ERROR ASRUtils::GetWiFiStationProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + lega_wlan_wifi_conf stationConfig; + + err = asr_wifi_get_config(&stationConfig); + SuccessOrExit(err); + + ChipLogProgress(DeviceLayer, "GetWiFiStationProvision"); + VerifyOrExit(strlen((const char *) stationConfig.wifi_ssid) != 0, err = CHIP_ERROR_INCORRECT_STATE); + + netInfo.NetworkId = kWiFiStationNetworkId; + netInfo.FieldPresent.NetworkId = true; + memcpy(netInfo.WiFiSSID, stationConfig.wifi_ssid, + min(strlen(reinterpret_cast(stationConfig.wifi_ssid)) + 1, sizeof(netInfo.WiFiSSID))); + + // Enforce that netInfo wifiSSID is null terminated + netInfo.WiFiSSID[kMaxWiFiSSIDLength] = '\0'; + + if (includeCredentials) + { + static_assert(sizeof(netInfo.WiFiKey) < 255, "Our min might not fit in netInfo.WiFiKeyLen"); + netInfo.WiFiKeyLen = static_cast(min(strlen((char *) stationConfig.wifi_key), sizeof(netInfo.WiFiKey))); + memcpy(netInfo.WiFiKey, stationConfig.wifi_key, netInfo.WiFiKeyLen); + } + +exit: + return err; +} + +CHIP_ERROR ASRUtils::ClearWiFiStationProvision(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + lega_wlan_wifi_conf stationConfig; + ChipLogProgress(DeviceLayer, "ClearWiFiStationProvision"); + // Clear the ASR WiFi station configuration. + memset(&stationConfig, 0, sizeof(stationConfig)); + ReturnLogErrorOnFailure(asr_wifi_set_config(&stationConfig)); + return err; +} + +CHIP_ERROR ASRUtils::asr_wifi_disconnect(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + ChipLogProgress(DeviceLayer, "asr_wifi_disconnect"); + + if (lega_wlan_close() != 0) + { + ChipLogError(DeviceLayer, "asr_wifi_disconnect() failed"); + err = CHIP_ERROR_INTERNAL; + } + return err; +} + +CHIP_ERROR ASRUtils::asr_wifi_connect(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + lega_wlan_wifi_conf stationConfig; + lega_wlan_init_type_t conf; + + memset(&conf, 0, sizeof(lega_wlan_init_type_t)); + conf.wifi_mode = STA; + conf.dhcp_mode = WLAN_DHCP_CLIENT; + asr_wifi_get_config(&stationConfig); + + strncpy((char *) conf.wifi_ssid, (char *) stationConfig.wifi_ssid, stationConfig.ssid_len); + + strncpy((char *) conf.wifi_key, (char *) stationConfig.wifi_key, stationConfig.key_len); + conf.security = stationConfig.security; + + // before wlan open with sta mode, make sure the wlan is closed. + // lega_wlan_close(); + + ChipLogProgress(DeviceLayer, "Connecting to AP : [%s]\r\n", StringOrNullMarker(conf.wifi_ssid)); + + lega_wlan_clear_pmk(); + + if (lega_wlan_open(&conf) != 0) + { + ChipLogError(DeviceLayer, "asr_wifi_connect() failed"); + err = CHIP_ERROR_INTERNAL; + } + + return err; +} diff --git a/src/platform/ASR/ASRUtils.h b/src/platform/ASR/ASRUtils.h new file mode 100644 index 00000000000000..ab865321253c98 --- /dev/null +++ b/src/platform/ASR/ASRUtils.h @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2021 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 + +#include "platform/internal/DeviceNetworkInfo.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include "lega_wlan_api.h" +#ifdef __cplusplus +} +#endif + +typedef struct +{ + char wifi_mode; /* refer to hal_wifi_type_t*/ + char security; /* security mode, refer to lega_wlan_security_e */ + char wifi_ssid[32]; /* in station mode, indicate SSID of the wlan needs to be connected. + in softap mode, indicate softap SSID*/ + char wifi_key[64]; /* in station mode, indicate Security key of the wlan needs to be connected, + in softap mode, indicate softap password.(ignored in an open system.) */ + uint32_t ssid_len; + uint32_t key_len; +} lega_wlan_wifi_conf; + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +class ASRUtils +{ +public: +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP + static CHIP_ERROR IsAPEnabled(bool & apEnabled); +#endif + static CHIP_ERROR IsStationEnabled(bool & staEnabled); + static bool IsStationProvisioned(void); + static CHIP_ERROR IsStationConnected(bool & connected); + static CHIP_ERROR SetStationConnected(bool connected); + static CHIP_ERROR EnableStationMode(void); + static struct netif * GetNetif(const char * ifKey); + static struct netif * GetStationNetif(void); + static bool IsInterfaceUp(const char * ifKey); + + static CHIP_ERROR GetWiFiStationProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials); + static CHIP_ERROR ClearWiFiStationProvision(void); + static CHIP_ERROR asr_wifi_get_config(lega_wlan_wifi_conf * conf); + static CHIP_ERROR asr_wifi_set_config(lega_wlan_wifi_conf * conf); + static CHIP_ERROR asr_wifi_disconnect(void); + static CHIP_ERROR asr_wifi_connect(void); + static CHIP_ERROR OnIPAddressAvailable(void); + static CHIP_ERROR ping_init(void); + static CHIP_ERROR GetWiFiSSID(char * buf, size_t bufSize); + static CHIP_ERROR StoreWiFiSSID(char * buf, size_t size); + static CHIP_ERROR GetWiFiPassword(char * buf, size_t bufSize); + static CHIP_ERROR StoreWiFiPassword(char * buf, size_t size); + static CHIP_ERROR GetWiFiSecurityCode(uint32_t & security); + static CHIP_ERROR StoreWiFiSecurityCode(uint32_t security); + static CHIP_ERROR wifi_get_mode(uint32_t & security); + static CHIP_ERROR wifi_set_mode(uint32_t security); +}; + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/BLEAppSvc.cpp b/src/platform/ASR/BLEAppSvc.cpp new file mode 100644 index 00000000000000..8c40aa3741f10b --- /dev/null +++ b/src/platform/ASR/BLEAppSvc.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. 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 \app_custom_svc.c + * + * @brief custom service db + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#ifdef __cplusplus +extern "C" { +#endif +#include "app.h" +#include "sonata_att.h" +#include "sonata_gap.h" +#include "sonata_gap_api.h" +#include "sonata_gatt_api.h" +#include +#ifdef __cplusplus +} +#endif +#include "BLEAppSvc.h" +#include +#include +#include +using namespace chip::DeviceLayer; +using namespace chip::DeviceLayer::Internal; + +static uint8_t current_connect_id = SONATA_ADDR_NONE; +static uint16_t service_handle = 0; +/* + * MACRO DEFINES + **************************************************************************************** + */ +#define APPSVC "APP_SVC" +/* + * ENUM DEFINITIONS + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +ble_gatt_att_reg_t matter_csvc_atts[CSVC_IDX_NB] = { + [CSVC_IDX_SVC] = { { { 0xF6, 0xFF, 0 }, 0, 0, 0 }, { 0, 0 } }, + // ATT_DECL_CHARACTERISTIC (Write) + [CSVC_IDX_RX_CHAR] = { { { 0X03, 0X28, 0 }, PRD_NA, 0, 0 }, { 0, 0 } }, + [CSVC_IDX_RX_VAL] = { { { 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 }, + PWR_NA, + 247, + PRI | SONATA_PERM(UUID_LEN, UUID_128) }, + { matter_rx_char_write_cb, 0 } }, + + // ATT_DECL_CHARACTERISTIC (Read,Notify) + [CSVC_IDX_TX_CHAR] = { { { 0X03, 0X28, 0 }, PRD_NA, 0, 0 }, { 0, 0 } }, + [CSVC_IDX_TX_VAL] = { { { 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 }, + PRD_NA | PNTF_NA | PIND_NA, + 247, + SONATA_PERM(UUID_LEN, UUID_128) }, + { 0, 0 } }, + [CSVC_IDX_TX_CFG] = { { { 0X02, 0X29, 0 }, PRD_NA | PWR_NA, 2, PRI }, { matter_tx_CCCD_write_cb, matter_tx_CCCD_read_cb } }, +}; +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ +void matter_ble_stack_open(void) +{ + ChipLogProgress(DeviceLayer, "matter_ble_stack_open\r\n"); + app_ble_stack_start(USER_MATTER_MODULE_ID); +} + +void matter_ble_start_adv(void) +{ + ble_adv_data_t data; + ble_scan_data_t scan_data; + memset(&data, 0, sizeof(ble_adv_data_t)); + memset(&scan_data, 0, sizeof(ble_scan_data_t)); + BLEMgrImpl().SetAdvertisingData((uint8_t *) &data.ble_advdata, (uint8_t *) &data.ble_advdataLen); + BLEMgrImpl().SetScanRspData((uint8_t *) &scan_data.ble_respdata, (uint8_t *) &scan_data.ble_respdataLen); + app_ble_advertising_start(APP_MATTER_ADV_IDX, &data, &scan_data); +} + +void matter_ble_stop_adv(void) +{ + app_ble_advertising_stop(APP_MATTER_ADV_IDX); +} +void matter_ble_add_service() +{ + int ret = 0; + ret = app_ble_gatt_add_svc_helper(&service_handle, sizeof(matter_csvc_atts) / sizeof(ble_gatt_att_reg_t), 1, matter_csvc_atts); + if (ret != 0) + { + ChipLogError(DeviceLayer, "matter_ble_add_service add service failed\r\n"); + } + else + { + ChipLogProgress(DeviceLayer, "matter_ble_add_service add service service_handle=%d\r\n", service_handle); + } +} +void matter_set_connection_id(uint8_t conId) +{ + ChipLogProgress(DeviceLayer, "matter_set_connection_id conId=%d\r\n", conId); + BLEMgrImpl().AllocConnectionState(conId); + current_connect_id = conId; +} + +uint16_t matter_ble_complete_event_handler(int opt_id, uint8_t status, uint16_t param, uint32_t dwparam) +{ + uint16_t ret = MATTER_EVENT_DONE_CONTINUE; + + switch (opt_id) + { + case SONATA_GAP_CMP_ADVERTISING_START: // 0x0F06 + if (is_matter_activity(param)) + { + BLEMgrImpl().SetAdvStartFlag(); + matter_ble_add_service(); + } + break; + case SONATA_GAP_CMP_ADVERTISING_STOP: + if (is_matter_activity(param)) + { + BLEMgrImpl().SetAdvEndFlag(); + } + break; + case SONATA_GATT_CMP_INDICATE: + if (current_connect_id != SONATA_ADDR_NONE) + { + BLEMgrImpl().SendIndicationConfirm(current_connect_id); + ret = MATTER_EVENT_DONE_FINISHED; + } + break; + case APP_BLE_STACK_EVENT_CONNECTION_REPORT: + matter_set_connection_id(param); + break; + case APP_BLE_STACK_EVENT_DISCONNECTED: + if (param == current_connect_id) + { + BLEMgrImpl().ReleaseConnectionState(current_connect_id); + current_connect_id = SONATA_ADDR_NONE; + ret = MATTER_EVENT_DONE_FINISHED; + } + PlatformMgr().ScheduleWork(BLEMgrImpl().DriveBLEState, 0); + break; + case APP_BLE_STACK_EVENT_MTU_CHANGED: + if (param == current_connect_id) + { + BLEMgrImpl().SetConnectionMtu(param, dwparam); + ret = MATTER_EVENT_DONE_FINISHED; + } + break; + default: + break; + } + return ret; +} + +void matter_tx_CCCD_write_cb(uint8_t * data, uint16_t size) +{ + BLEMgrImpl().HandleTXCharCCCDWrite(current_connect_id, size, data); +} +void matter_rx_char_write_cb(uint8_t * data, uint16_t size) +{ + BLEMgrImpl().HandleRXCharWrite(current_connect_id, size, data); +} +void matter_tx_CCCD_read_cb(uint8_t * data, uint16_t * size) +{ + BLEMgrImpl().HandleTXCharCCCDRead(current_connect_id, size, data); +} + +void matter_tx_char_send_indication(uint8_t conId, uint16_t size, uint8_t * data) +{ + ChipLogProgress(DeviceLayer, "matter_tx_char_send_indication conId=%d size=%d data=%p service_handle=%d", conId, size, data, + service_handle); + app_ble_gatt_data_send(conId, service_handle, CSVC_IDX_TX_VAL, size, data); +} + +void matter_init_callback(void) +{ + ble_matter_event_callback_reg(matter_ble_complete_event_handler); +} diff --git a/src/platform/ASR/BLEAppSvc.h b/src/platform/ASR/BLEAppSvc.h new file mode 100644 index 00000000000000..1e063e4b6b2a80 --- /dev/null +++ b/src/platform/ASR/BLEAppSvc.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. 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 \app_custom_svc.h + * + * @brief custom service db + * + **************************************************************************************** + */ +#ifndef _APP_CUSTOM_SVC_H_ +#define _APP_CUSTOM_SVC_H_ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#ifdef __cplusplus +extern "C" { +#endif +#include "sonata_ble_api.h" +#include "sonata_gatt_api.h" + +/* + * MACRO DEFINES + **************************************************************************************** + */ + +/* + * ENUM DEFINITIONS + **************************************************************************************** + */ + +enum csvc_att_db_handles +{ + CSVC_IDX_SVC, + CSVC_IDX_RX_CHAR, + CSVC_IDX_RX_VAL, + CSVC_IDX_TX_CHAR, + CSVC_IDX_TX_VAL, + CSVC_IDX_TX_CFG, + CSVC_IDX_NB, +}; + +enum _matter_event_states +{ + MATTER_EVENT_DONE_CONTINUE, + MATTER_EVENT_DONE_FINISHED, +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ +void matter_ble_add_service(); + +uint16_t matter_ble_complete_event_handler(int opt_id, uint8_t status, uint16_t param, uint32_t dwparam); + +void matter_ble_stop_adv(); + +void matter_ble_start_adv(); + +void matter_set_connection_id(uint8_t conId); + +void matter_tx_CCCD_write_cb(uint8_t * data, uint16_t size); +void matter_rx_char_write_cb(uint8_t * data, uint16_t size); +void matter_tx_CCCD_read_cb(uint8_t * data, uint16_t * size); + +void matter_tx_char_send_indication(uint8_t conId, uint16_t size, uint8_t * data); + +void matter_init_callback(void); +void matter_ble_stack_open(void); + +#ifdef __cplusplus +} +#endif +#endif // BLE_SOC_APP_CUSTOM_SVC_H diff --git a/src/platform/ASR/BLEManagerImpl.cpp b/src/platform/ASR/BLEManagerImpl.cpp new file mode 100644 index 00000000000000..791f36a745204c --- /dev/null +++ b/src/platform/ASR/BLEManagerImpl.cpp @@ -0,0 +1,662 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2020 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. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + +#include "BLEAppSvc.h" +#include +#include +#include +#include + +#include "app.h" + +#if 0 // enable ble log +#if (CFG_EASY_LOG_ENABLE == 1) +#include "elog.h" +#else +#define log_i printf +#endif +#else +#define log_i(format, ...) +#endif + +#define CHIP_MAX_ADV_DATA_LEN 31 +#define CHIP_ADV_DATA_TYPE_FLAGS 0x01 +#define CHIP_ADV_DATA_FLAGS 0x06 +#define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16 + +using namespace ::chip; +using namespace ::chip::Ble; + +#define BLE_SERVICE_DATA_SIZE 10 + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +namespace { + +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 } }; + +} // unnamed namespace + +BLEManagerImpl BLEManagerImpl::sInstance; + +#ifdef __cplusplus +extern "C" { +#endif +#include "sonata_ble_api.h" +#include "sonata_gap.h" +#include "sonata_gap_api.h" +#include "sonata_utils_api.h" +int init_ble_task(void); +int ble_close(void); +// uint16_t app_ble_stop_adv(uint8_t adv_idx); +extern uint8_t ble_open; +#ifdef __cplusplus +} +#endif + +CHIP_ERROR BLEManagerImpl::_Init() +{ + CHIP_ERROR err; + + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + // Initialize the CHIP BleLayer. + err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer()); + SuccessOrExit(err); + log_i("%s:%s:%d err=%s ble_open=%d\r\n", "BLEManagerImpl", __func__, __LINE__, ErrorStr(err), (int) ble_open); + matter_init_callback(); + if (ble_open == 0) + { + log_i("%s:%s:%d err=%s ble_open=%d\r\n", "BLEManagerImpl", __func__, __LINE__, ErrorStr(err), (int) ble_open); + // init_ble_task(); + matter_ble_stack_open(); + } + else + { + log_i("ble is alread open!\n"); + } + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; + if (CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART) + { + mFlags.Set(Flags::kFlag_AdvertisingEnabled, true); + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + } + else + { + mFlags.Set(Flags::kFlag_AdvertisingEnabled, false); + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + } + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + mNumCons = 0; + memset(mCons, 0, sizeof(mCons)); + memset(mDeviceName, 0, sizeof(mDeviceName)); + + ChipLogProgress(DeviceLayer, "BLEManagerImpl::Init() complete"); + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + +exit: + log_i("%s:%s:%d err=%s\r\n", "BLEManagerImpl", __func__, __LINE__, ErrorStr(err)); + return err; +} + +bool BLEManagerImpl::_IsAdvertisingEnabled(void) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + return mFlags.Has(Flags::kFlag_AdvertisingEnabled); +} + +CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + log_i("%s:%s:%d val=%d\r\n", "BLEManagerImpl", __func__, __LINE__, val); + VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (mFlags.Has(Flags::kFlag_AdvertisingEnabled) != val) + { + mFlags.Set(Flags::kFlag_AdvertisingEnabled, val); + PlatformMgr().ScheduleWork(DriveBLEState, 0); + } + +exit: + return err; +} + +/* + * TODO + */ +CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) +{ + (void) (mode); + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported) + { + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + if (strlen(mDeviceName) >= bufSize) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + strcpy(buf, mDeviceName); + ChipLogProgress(DeviceLayer, "Getting device name to : \"%s\"", StringOrNullMarker(mDeviceName)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + return CHIP_NO_ERROR; +} + +uint16_t BLEManagerImpl::_NumConnections(void) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + return mNumCons; +} + +void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) +{ + // log_i("\r\n%s:%s:%d event->Type=%d\r\n","BLEManagerImpl",__func__,__LINE__,event->Type); + switch (event->Type) + { + case DeviceEventType::kCHIPoBLESubscribe: + HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + { + ChipDeviceEvent connectionEvent; + connectionEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished; + PlatformMgr().PostEventOrDie(&connectionEvent); + } + break; + + case DeviceEventType::kCHIPoBLEUnsubscribe: + HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + break; + + case DeviceEventType::kCHIPoBLEWriteReceived: + HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX, + PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data)); + break; + + case DeviceEventType::kCHIPoBLENotifyConfirm: + HandleIndicationConfirmation(event->CHIPoBLENotifyConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + break; + + case DeviceEventType::kCHIPoBLEIndicateConfirm: + HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX); + break; + + case DeviceEventType::kCHIPoBLEConnectionError: + HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason); + break; + + case DeviceEventType::kServiceProvisioningChange: + case DeviceEventType::kWiFiConnectivityChange: + + // Force the advertising configuration to be refreshed to reflect new provisioning state. + ChipLogProgress(DeviceLayer, "Updating advertising data"); + // mFlags.Clear(Flags::kAdvertisingConfigured); + // mFlags.Set(Flags::kAdvertisingRefreshNeeded); + + DriveBLEState(); + + default: + break; + } +} + +bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported"); + return false; +} + +bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported"); + return false; +} + +bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + return true; +} + +uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const +{ + CHIPoBLEConState * p_conn; + + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + /* Check if target connection state exists. */ + p_conn = BLEManagerImpl::sInstance.GetConnectionState(conId); + + if (!p_conn) + { + return 0; + } + else + { + log_i("%s:%s:%d p_conn->Mtu=%d\r\n", "BLEManagerImpl", __func__, __LINE__, p_conn->Mtu); + return p_conn->Mtu; + } +} + +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); + + // log_i( "%s:%s:%d Sending indication for CHIPoBLE TX characteristic (con %u, len %u)\r\n", + // "BLEManagerImpl",__func__,__LINE__,conId, data->DataLength()); log_i("character + // id=%02x-%02x-%02x\r\n",charId->bytes[0],charId->bytes[1],charId->bytes[2]); + VerifyOrExit(conState != NULL, err = CHIP_ERROR_INVALID_ARGUMENT); + + matter_tx_char_send_indication(conId, data->DataLength(), data->Start()); + +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 data) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported"); + return false; +} + +bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, + PacketBufferHandle data) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + ChipLogError(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) +{ + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported"); + return false; +} + +void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {} + +void BLEManagerImpl::DriveBLEState(void) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + // Perform any initialization actions that must occur after the CHIP task is running. + if (!mFlags.Has(Flags::kFlag_AsyncInitCompleted)) + { + mFlags.Set(Flags::kFlag_AsyncInitCompleted, true); + } + ChipLogProgress(DeviceLayer, "%s:%s:%d kFlag_AdvertisingEnabled=%d \r\n", "BLEManagerImpl", __func__, __LINE__, + mFlags.Has(Flags::kFlag_AdvertisingEnabled)); + + // If the application has enabled CHIPoBLE and BLE advertising... + if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && + mFlags.Has(Flags::kFlag_AdvertisingEnabled) +#if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION + // and no connections are active... + && (mNumCons == 0) +#endif + ) + { + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + // Start/re-start SoftDevice advertising if not already advertising, or if the + // advertising state of the SoftDevice needs to be refreshed. + if (!mFlags.Has(Flags::kFlag_Advertising) || mFlags.Has(Flags::kFlag_AdvertisingRefreshNeeded)) + { + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started"); + matter_ble_start_adv(); + } + } + + // Otherwise, stop advertising if currently active. + else + { + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + if (mFlags.Has(Flags::kFlag_Advertising)) + { + ChipLogProgress(DeviceLayer, "CHIPoBLE stop advertising"); + // sonata_ble_stop_advertising(); + matter_ble_stop_adv(); + } + } + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; + } +} + +void BLEManagerImpl::SetAdvertisingData(uint8_t * data, uint8_t * len) +{ + CHIP_ERROR err; + uint8_t advData[CHIP_MAX_ADV_DATA_LEN]; + uint8_t index = 0; + uint16_t discriminator; + chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo; + + log_i("%s:%s:%d\r\n", "BLEManagerImpl", __func__, __LINE__); + + err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo); + if (err != CHIP_NO_ERROR) + { + log_i("GetBLEDeviceIdentificationInfo error\r\n"); + return; + } + discriminator = deviceIdInfo.GetDeviceDiscriminator(); + if (err != CHIP_NO_ERROR) + { + log_i("GetSetupDiscriminator error err=%s\r\n", ErrorStr(err)); + return; + } + + // if (!mFlags.Has(Flags::kUseCustom DeviceName)) + { + snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator); + mDeviceName[32] = 0; + ChipLogError(DeviceLayer, "%s:%s:%d mDeviceName=%s\r\n", "BLEManagerImpl", __func__, __LINE__, mDeviceName); + } + + memset(advData, 0, sizeof(advData)); + + advData[index++] = 0x0B; // length + advData[index++] = SONATA_GAP_AD_TYPE_SERVICE_16_BIT_DATA; // AD type: (Service Data - 16-bit UUID) + advData[index++] = ShortUUID_CHIPoBLEService[0]; // AD value + advData[index++] = ShortUUID_CHIPoBLEService[1]; // AD value + + if (index + sizeof(deviceIdInfo) > CHIP_MAX_ADV_DATA_LEN) + { + ChipLogError(DeviceLayer, "SetAdvertisingData advdata extend len=%d\r\n", index); + return; + } + memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo)); + index = static_cast(index + sizeof(deviceIdInfo)); + + if (index + strlen(mDeviceName) + 2 > CHIP_MAX_ADV_DATA_LEN) + { + ChipLogError(DeviceLayer, "SetAdvertisingData advdata extend len=%d\r\n", index); + return; + } + advData[index++] = strlen(mDeviceName) + 1; + advData[index++] = SONATA_GAP_AD_TYPE_COMPLETE_NAME; + + memcpy(&advData[index], mDeviceName, strlen(mDeviceName)); + index = static_cast(index + strlen(mDeviceName)); + + *len = index; + memcpy(data, advData, index); + return; +} + +void BLEManagerImpl::SetScanRspData(uint8_t * data, uint8_t * len) +{ + uint8_t advData[CHIP_MAX_ADV_DATA_LEN]; + uint8_t index = 0; + + advData[index++] = strlen(mDeviceName) + 1; + advData[index++] = SONATA_GAP_AD_TYPE_COMPLETE_NAME; + if (index + strlen(mDeviceName) > CHIP_MAX_ADV_DATA_LEN) + { + ChipLogError(DeviceLayer, "advdata extend len=%d\r\n", index); + return; + } + memcpy(&advData[index], mDeviceName, strlen(mDeviceName)); + index = static_cast(index + strlen(mDeviceName)); + + *len = index; + memcpy(data, advData, index); + return; +} + +void BLEManagerImpl::SetAdvStartFlag(void) +{ + CHIP_ERROR err; + + mFlags.Set(Flags::kFlag_Advertising, true); + mFlags.Set(Flags::kFlag_AdvertisingRefreshNeeded, false); + + ChipDeviceEvent advChange; + advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; + advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started; + err = PlatformMgr().PostEvent(&advChange); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "SetAdvStartFlag to error: %s", ErrorStr(err)); + } +} + +void BLEManagerImpl::SetAdvEndFlag(void) +{ + CHIP_ERROR err; + + mFlags.Set(Flags::kFlag_Advertising, false); + + ChipDeviceEvent advChange; + advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange; + advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped; + err = PlatformMgr().PostEvent(&advChange); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "SetAdvEndFlag to error: %s", ErrorStr(err)); + } +} + +bool BLEManagerImpl::HandleRXCharWrite(uint8_t connection_id, uint16_t length, uint8_t * value) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + PacketBufferHandle buf; + + log_i("%s:%s:%d Write request received for CHIPoBLE RX characteristic (con %u, len %u)\r\n", "BLEManagerImpl", __func__, + __LINE__, connection_id, length); + + // Copy the data to a packet buffer. + buf = System::PacketBufferHandle::NewWithData(value, length, 0, 0); + VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY); + + // Post an event to the Chip queue to deliver the data into the Chip stack. + ChipDeviceEvent event; + event.Type = DeviceEventType::kCHIPoBLEWriteReceived; + event.CHIPoBLEWriteReceived.ConId = connection_id; + event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease(); + err = PlatformMgr().PostEvent(&event); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err)); + return false; + } + else + return true; +} + +void BLEManagerImpl::HandleTXCharCCCDRead(uint8_t connection_id, uint16_t * length, uint8_t * value) +{ + CHIPoBLEConState * conState = NULL; + log_i("%s:%s:%d read request received for CHIPoBLE TX CCCD\r\n", "BLEManagerImpl", __func__, __LINE__); + // Find the connection state record. + conState = GetConnectionState(connection_id); + if (NULL != conState) + { + *length = 2; + value[0] = conState->Subscribed ? 1 : 0; + log_i("%s:%s:%d read request received for CHIPoBLE TX CCCD conState->Subscribed=%d\r\n", "BLEManagerImpl", __func__, + __LINE__, conState->Subscribed); + } +} + +bool BLEManagerImpl::HandleTXCharCCCDWrite(uint8_t connection_id, uint16_t length, uint8_t * value) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + bool indicationsEnabled = false; + CHIPoBLEConState * conState; + + conState = GetConnectionState(connection_id); + VerifyOrExit(conState != NULL, err = CHIP_ERROR_NO_MEMORY); + log_i("%s:%s:%d length=%d value[0]=%d value[1]=%d\r\n", "BLEManagerImpl", __func__, __LINE__, length, value[0], value[1]); + // Determine if the client is enabling or disabling indications. + indicationsEnabled = ((length > 0) && (value[0] != 0)); + + // 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. + + ChipDeviceEvent event; + event.Type = (indicationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe; + event.CHIPoBLESubscribe.ConId = connection_id; + err = PlatformMgr().PostEvent(&event); + + conState->Subscribed = indicationsEnabled; + log_i("\r\nCHIPoBLE %s received\r\n", indicationsEnabled ? "subscribe" : "unsubscribe"); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err)); + return false; + } + else + return true; +} + +void BLEManagerImpl::SendIndicationConfirm(uint16_t conId) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + ChipDeviceEvent event; + CHIPoBLEConState * pConnection = GetConnectionState(conId); + if (pConnection) + { + // log_i(" SendIndicationConfirm conId=%d\r\n",conId); + event.Type = DeviceEventType::kCHIPoBLENotifyConfirm; + event.CHIPoBLENotifyConfirm.ConId = conId; + err = PlatformMgr().PostEvent(&event); + if (err != CHIP_NO_ERROR) + { + log_i("notify confirm failed\r\n"); + } + } +} + +void BLEManagerImpl::SetConnectionMtu(uint16_t conId, uint16_t mtu) +{ + CHIPoBLEConState * pConnection = GetConnectionState(conId); + if (pConnection) + { + pConnection->Mtu = mtu; + log_i("%s:%s:%d set conId=%d mtu=%d\r\n", "BLEManagerImpl", __func__, __LINE__, conId, mtu); + return; + } + ChipLogError(DeviceLayer, "set mtu failed"); +} + +BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::AllocConnectionState(uint16_t conId) +{ + log_i("%s:%s:%d conId=%d\r\n", "BLEManagerImpl", __func__, __LINE__, conId); + for (uint16_t i = 0; i < kMaxConnections; i++) + { + if (mCons[i].connected == false) + { + mCons[i].ConId = conId; + mCons[i].Mtu = 500; + mCons[i].connected = true; + + mNumCons++; + + return &mCons[i]; + } + } + ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState"); + return NULL; +} + +BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint16_t conId) +{ + // log_i("%s:%s:%d conId=%d\r\n","BLEManagerImpl",__func__,__LINE__,conId); + for (uint16_t i = 0; i < kMaxConnections; i++) + { + if (mCons[i].ConId == conId) + { + return &mCons[i]; + } + } + ChipLogError(DeviceLayer, "Failed to find CHIPoBLEConState"); + return NULL; +} + +bool BLEManagerImpl::ReleaseConnectionState(uint16_t conId) +{ + log_i("%s:%s:%d conId=%d\r\n", "BLEManagerImpl", __func__, __LINE__, conId); + for (uint16_t i = 0; i < kMaxConnections; i++) + { + if (mCons[i].ConId == conId) + { + memset(&mCons[i], 0, sizeof(CHIPoBLEConState)); + mNumCons--; + return true; + } + } + ChipLogError(DeviceLayer, "Failed to delete CHIPoBLEConState"); + return false; +} + +void BLEManagerImpl::DriveBLEState(intptr_t arg) +{ + sInstance.DriveBLEState(); +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip + +#endif diff --git a/src/platform/ASR/BLEManagerImpl.h b/src/platform/ASR/BLEManagerImpl.h new file mode 100644 index 00000000000000..e29f4d0a671852 --- /dev/null +++ b/src/platform/ASR/BLEManagerImpl.h @@ -0,0 +1,165 @@ +/* + * + * Copyright (c) 2021 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 + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +/** + * Concrete implementation of the NetworkProvisioningServer singleton object for the PSoC 6 platform. + */ +class BLEManagerImpl final : public BLEManager, + private Ble::BleLayer, + private Ble::BlePlatformDelegate, + private Ble::BleApplicationDelegate +{ + // Allow the BLEManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend BLEManager; + + // ===== Members that implement the BLEManager internal interface. + + CHIP_ERROR _Init(void); + void _Shutdown() {} + bool _IsAdvertisingEnabled(void); + CHIP_ERROR _SetAdvertisingEnabled(bool val); + bool _IsFastAdvertisingEnabled(void); + bool _IsAdvertising(void); + CHIP_ERROR _SetAdvertisingMode(BLEAdvertisingMode mode); + CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize); + CHIP_ERROR _SetDeviceName(const char * deviceName); + uint16_t _NumConnections(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); + ::chip::Ble::BleLayer * _GetBleLayer(void); + + // ===== Members that implement virtual methods on BlePlatformDelegate. + + bool SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + bool CloseConnection(BLE_CONNECTION_OBJECT conId) override; + uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override; + bool SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle data) override; + bool SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle data) override; + bool SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, + System::PacketBufferHandle data) override; + bool SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, const Ble::ChipBleUUID * svcId, + const Ble::ChipBleUUID * charId) override; + + // ===== Members that implement virtual methods on BleApplicationDelegate. + + void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override; + + // ===== Members for internal use by the following friends. + + friend BLEManager & BLEMgr(void); + friend BLEManagerImpl & BLEMgrImpl(void); + +public: + static BLEManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + enum class Flags : uint16_t + { + kFlag_AsyncInitCompleted = 0x0001, /**< One-time asynchronous initialization actions have been performed. */ + kFlag_AdvertisingEnabled = 0x0002, /**< The application has enabled CHIPoBLE advertising. */ + kFlag_FastAdvertisingEnabled = 0x0004, /**< The application has enabled fast advertising. */ + kFlag_Advertising = 0x0008, /**< The system is currently CHIPoBLE advertising. */ + kFlag_AdvertisingRefreshNeeded = + 0x0010, /**< The advertising state/configuration has changed, but the SoftDevice has yet to be updated. */ + kFlag_DeviceNameSet = 0x0020, + kFlag_StackInitialized = 0x0040, + }; + + enum + { + kMaxConnections = BLE_LAYER_NUM_BLE_ENDPOINTS, + }; + + struct CHIPoBLEConState + { + // System::PacketBuffer * PendingIndBuf; + uint16_t ConId; + uint16_t Mtu; + bool connected; + bool Subscribed; + }; + + CHIPoBLEConState mCons[3]; + uint16_t mNumCons; + CHIPoBLEServiceMode mServiceMode; + BitFlags mFlags; + char mDeviceName[32 + 1]; + + void DriveBLEState(void); + void SetAdvertisingData(uint8_t * data, uint8_t * len); + void SetScanRspData(uint8_t * data, uint8_t * len); + void SetAdvStartFlag(void); + void SetAdvEndFlag(void); + CHIPoBLEConState * AllocConnectionState(uint16_t conId); + CHIPoBLEConState * GetConnectionState(uint16_t conId); + bool ReleaseConnectionState(uint16_t conId); + void SetConnectionMtu(uint16_t conId, uint16_t mtu); + + static void DriveBLEState(intptr_t arg); + + void HandleTXCharCCCDRead(uint8_t connection_id, uint16_t * length, uint8_t * value); + bool HandleRXCharWrite(uint8_t connection_id, uint16_t length, uint8_t * value); + bool HandleTXCharCCCDWrite(uint8_t connection_id, uint16_t length, uint8_t * value); + void SendIndicationConfirm(uint16_t conId); +}; + +/** + * Returns a reference to the public interface of the BLEManager singleton object. + * + * Internal components should use this to access features of the BLEManager object + * that are common to all platforms. + */ +inline BLEManager & BLEMgr(void) +{ + return BLEManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the BLEManager singleton object. + * + * Internal components can use this to gain access to features of the BLEManager + * that are specific to the PSoC 6 platform. + */ +inline BLEManagerImpl & BLEMgrImpl(void) +{ + return BLEManagerImpl::sInstance; +} + +inline Ble::BleLayer * BLEManagerImpl::_GetBleLayer() +{ + return this; +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip + +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/ASR/BUILD.gn b/src/platform/ASR/BUILD.gn new file mode 100755 index 00000000000000..b1de3eaf3c2af9 --- /dev/null +++ b/src/platform/ASR/BUILD.gn @@ -0,0 +1,89 @@ +# Copyright (c) 2023 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/ASR/args.gni") +import("${chip_root}/src/platform/device.gni") + +assert(chip_device_platform == "asr") + +static_library("ASR") { + sources = [] + sources += [ + "../SingletonConfigurationManager.cpp", + "ASRConfig.cpp", + "ASRConfig.h", + "ASRFactoryDataProvider.cpp", + "ASRUtils.cpp", + "ASRUtils.h", + "BLEManagerImpl.cpp", + "BLEManagerImpl.h", + "BlePlatformConfig.h", + "CHIPDevicePlatformConfig.h", + "CHIPDevicePlatformEvent.h", + "CHIPPlatformConfig.h", + "ConfigurationManagerImpl.cpp", + "ConfigurationManagerImpl.h", + "ConnectivityManagerImpl.cpp", + "ConnectivityManagerImpl.h", + "DiagnosticDataProviderImpl.cpp", + "DiagnosticDataProviderImpl.h", + "InetPlatformConfig.h", + "KeyValueStoreManagerImpl.cpp", + "KeyValueStoreManagerImpl.h", + "Logging.cpp", + "LwIPCoreLock.cpp", + "NetworkCommissioningDriver.h", + "NetworkCommissioningWiFiDriver.cpp", + "PlatformManagerImpl.cpp", + "PlatformManagerImpl.h", + "SystemPlatformConfig.h", + "SystemTimeSupport.cpp", + "WarmPlatformConfig.h", + ] + + if (chip_config_network_layer_ble) { + sources += [ + "BLEAppSvc.cpp", + "BLEAppSvc.h", + ] + } + + #lwip ip6 hook + sources += [ + "route_hook/asr_route_hook.c", + "route_hook/asr_route_hook.h", + "route_hook/asr_route_table.c", + "route_hook/asr_route_table.h", + ] + + deps = [ + "${chip_root}/src/lib/dnssd:platform_header", + "${chip_root}/src/setup_payload", + ] + + public_deps = [ + "${chip_root}/src/crypto", + "${chip_root}/src/platform:platform_base", + ] + + if (chip_enable_ota_requestor) { + sources += [ + "ASROTAImageProcessor.cpp", + "ASROTAImageProcessor.h", + ] + } +} diff --git a/src/platform/ASR/BlePlatformConfig.h b/src/platform/ASR/BlePlatformConfig.h new file mode 100755 index 00000000000000..261bef22fbd6a9 --- /dev/null +++ b/src/platform/ASR/BlePlatformConfig.h @@ -0,0 +1,33 @@ +/* + * + * Copyright (c) 2021 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 + +// ==================== Platform Adaptations ==================== + +#define BLE_CONNECTION_OBJECT uint16_t +#define BLE_CONNECTION_UNINITIALIZED ((uint16_t) 0xFFFF) +#define BLE_MAX_RECEIVE_WINDOW_SIZE 5 + +#define BLE_CONFIG_ERROR_FORMAT PRId32 +#define BLE_CONFIG_ERROR_TYPE uint32_t +#define BLE_CONFIG_NO_ERROR 0 +#define BLE_CONFIG_ERROR_MIN 6000000 +#define BLE_CONFIG_ERROR_MAX 6000999 +#define _BLE_CONFIG_ERROR(e) (BLE_CONFIG_ERROR_MIN + (e)) diff --git a/src/platform/ASR/CHIPDevicePlatformConfig.h b/src/platform/ASR/CHIPDevicePlatformConfig.h new file mode 100644 index 00000000000000..e1f2e25ef23c30 --- /dev/null +++ b/src/platform/ASR/CHIPDevicePlatformConfig.h @@ -0,0 +1,42 @@ +/* + * + * Copyright (c) 2021 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 + +// ==================== Platform Adaptations ==================== + +#define CHIP_DEVICE_CONFIG_LWIP_WIFI_STATION_IF_NAME "asr" + +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "ASR" +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8001 +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "asr582x" +#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE 1024 * 8 +#define CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY 1 +#define CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1 + +#define CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE 25 + +#define CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 0 diff --git a/src/platform/ASR/CHIPDevicePlatformEvent.h b/src/platform/ASR/CHIPDevicePlatformEvent.h new file mode 100755 index 00000000000000..b222ec17308236 --- /dev/null +++ b/src/platform/ASR/CHIPDevicePlatformEvent.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (c) 2021 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 + +#include + +namespace chip { +namespace DeviceLayer { + +namespace DeviceEventType { +} // namespace DeviceEventType + +/** + * Represents platform-specific event information for the ASR platform. + */ +struct ChipDevicePlatformEvent final +{ +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/CHIPPlatformConfig.h b/src/platform/ASR/CHIPPlatformConfig.h new file mode 100755 index 00000000000000..ecdb8ff54cb558 --- /dev/null +++ b/src/platform/ASR/CHIPPlatformConfig.h @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2021 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. + */ + +/** + * @file + * Platform-specific configuration overrides for CHIP on + * the ASR platform. + */ + +#pragma once + +// ==================== General Platform Adaptations ==================== + +#define CHIP_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID "enc-msg-counter" + +#define CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH 15 + +#define CHIP_CONFIG_ERROR_TYPE uint32_t +#define CHIP_CONFIG_NO_ERROR 0 +#define CHIP_CONFIG_ERROR_MIN 4000000 +#define CHIP_CONFIG_ERROR_MAX 4000999 +#define CHIP_CONFIG_ERROR_FORMAT PRId32 + +#define ASN1_CONFIG_ERROR_TYPE uint32_t +#define ASN1_CONFIG_NO_ERROR 0 +#define ASN1_CONFIG_ERROR_MIN 5000000 +#define ASN1_CONFIG_ERROR_MAX 5000999 + +#define CHIP_CONFIG_ABORT() abort() + +// ==================== Security Adaptations ==================== + +// ==================== General Configuration Overrides ==================== + +#ifndef CHIP_CONFIG_MAX_FABRICS +#define CHIP_CONFIG_MAX_FABRICS 5 +#endif // CHIP_CONFIG_MAX_FABRICS + +#ifndef CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS +#define CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS 16 +#endif // CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS + +#ifndef CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS +#define CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS 20 +#endif // CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS + +#ifndef CHIP_LOG_FILTERING +#define CHIP_LOG_FILTERING 0 +#endif // CHIP_LOG_FILTERING diff --git a/src/platform/ASR/ConfigurationManagerImpl.cpp b/src/platform/ASR/ConfigurationManagerImpl.cpp new file mode 100644 index 00000000000000..0704a9ddadbb92 --- /dev/null +++ b/src/platform/ASR/ConfigurationManagerImpl.cpp @@ -0,0 +1,233 @@ +/* + * + * Copyright (c) 2021 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. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include + +#include +#include +#include +#ifdef CFG_PLF_RV32 +#include "alto_common.h" +#else +#include +#endif +namespace chip { +namespace DeviceLayer { + +using namespace ::chip::DeviceLayer::Internal; + +ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance() +{ + static ConfigurationManagerImpl sInstance; + return sInstance; +} + +CHIP_ERROR ConfigurationManagerImpl::Init() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint32_t rebootCount; + + // Save out software version on first boot + if (!ASRConfig::ConfigValueExists(ASRConfig::kConfigKey_SoftwareVersion)) + { + err = StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + SuccessOrExit(err); + } + + if (ASRConfig::ConfigValueExists(ASRConfig::kCounterKey_RebootCount)) + { + err = GetRebootCount(rebootCount); + SuccessOrExit(err); + + err = StoreRebootCount(rebootCount + 1); + SuccessOrExit(err); + } + else + { + // The first boot after factory reset of the Node. + err = StoreRebootCount(1); + SuccessOrExit(err); + } + + if (!ASRConfig::ConfigValueExists(ASRConfig::kCounterKey_TotalOperationalHours)) + { + err = StoreTotalOperationalHours(0); + SuccessOrExit(err); + } + + // Initialize the generic implementation base class. + err = Internal::GenericConfigurationManagerImpl::Init(); + VerifyOrReturnError(CHIP_NO_ERROR == err, err); + +exit: + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount) +{ + return ReadConfigValue(ASRConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount) +{ + return WriteConfigValue(ASRConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::GetSoftwareVersion(uint32_t & softwareVer) +{ + return ReadConfigValue(ASRConfig::kConfigKey_SoftwareVersion, softwareVer); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreSoftwareVersion(uint32_t softwareVer) +{ + return WriteConfigValue(ASRConfig::kConfigKey_SoftwareVersion, softwareVer); +} + +CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + return ReadConfigValue(ASRConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours) +{ + return WriteConfigValue(ASRConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) +{ + lega_wlan_get_mac_address(buf); + + return CHIP_NO_ERROR; +} + +bool ConfigurationManagerImpl::CanFactoryReset() +{ + // TODO: query the application to determine if factory reset is allowed. + return true; +} + +void ConfigurationManagerImpl::InitiateFactoryReset() +{ + PlatformMgr().ScheduleWork(DoFactoryReset); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) +{ + uint32_t in = 0; + CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key, &in, 4); + value = in; + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) +{ + return PersistedStorage::KeyValueStoreMgr().Put(key, static_cast(&value), 4); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, bool & val) +{ + return ASRConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint32_t & val) +{ + return ASRConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint64_t & val) +{ + return ASRConfig::ReadConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) +{ + return ASRConfig::ReadConfigValueStr(key, buf, bufSize, outLen); +} + +CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) +{ + return ASRConfig::ReadConfigValueBin(key, buf, bufSize, outLen); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, bool val) +{ + return ASRConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint32_t val) +{ + return ASRConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint64_t val) +{ + return ASRConfig::WriteConfigValue(key, val); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str) +{ + return ASRConfig::WriteConfigValueStr(key, str); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str, size_t strLen) +{ + return ASRConfig::WriteConfigValueStr(key, str, strLen); +} + +CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) +{ + return ASRConfig::WriteConfigValueBin(key, data, dataLen); +} + +void ConfigurationManagerImpl::RunConfigUnitTest(void) +{ + ASRConfig::RunConfigUnitTest(); +} + +void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) +{ + CHIP_ERROR err; + + ChipLogProgress(DeviceLayer, "Performing factory reset"); + + err = ASRConfig::FactoryResetConfig(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", ErrorStr(err)); + } + + // Restart the system. + ChipLogProgress(DeviceLayer, "System restarting"); +#ifdef CFG_PLF_RV32 + asr_system_reset(); +#else + NVIC_SystemReset(); +#endif +} + +ConfigurationManager & ConfigurationMgrImpl() +{ + return ConfigurationManagerImpl::GetDefaultInstance(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/ConfigurationManagerImpl.h b/src/platform/ASR/ConfigurationManagerImpl.h new file mode 100755 index 00000000000000..74b021f4a428db --- /dev/null +++ b/src/platform/ASR/ConfigurationManagerImpl.h @@ -0,0 +1,83 @@ +/* + * + * Copyright (c) 2021 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 + +#include + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the ConfigurationManager singleton object for the ASR platform. + */ +class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImpl +{ +public: + CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override; + CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override; + CHIP_ERROR GetSoftwareVersion(uint32_t & softwareVer) override; + CHIP_ERROR StoreSoftwareVersion(uint32_t softwareVer); + CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override; + CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours) override; + // This returns an instance of this class. + static ConfigurationManagerImpl & GetDefaultInstance(); + +private: + // ===== Members that implement the ConfigurationManager public interface. + + CHIP_ERROR Init(void) override; + CHIP_ERROR GetPrimaryWiFiMACAddress(uint8_t * buf) override; + bool CanFactoryReset(void) override; + void InitiateFactoryReset(void) override; + CHIP_ERROR ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) override; + CHIP_ERROR WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) override; + + // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>. + + // ===== Members that implement the GenericConfigurationManagerImpl protected interface. + CHIP_ERROR ReadConfigValue(Key key, bool & val) override; + CHIP_ERROR ReadConfigValue(Key key, uint32_t & val) override; + CHIP_ERROR ReadConfigValue(Key key, uint64_t & val) override; + CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) override; + CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) override; + CHIP_ERROR WriteConfigValue(Key key, bool val) override; + CHIP_ERROR WriteConfigValue(Key key, uint32_t val) override; + CHIP_ERROR WriteConfigValue(Key key, uint64_t val) override; + CHIP_ERROR WriteConfigValueStr(Key key, const char * str) override; + CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen) override; + CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) override; + void RunConfigUnitTest(void) override; + + // ===== Private members reserved for use by this class only. + + static void DoFactoryReset(intptr_t arg); +}; + +/** + * Returns the platform-specific implementation of the ConfigurationManager object. + * + * Applications can use this to gain access to features of the ConfigurationManager + * that are specific to the selected platform. + */ +ConfigurationManager & ConfigurationMgrImpl(); + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/ConnectivityManagerImpl.cpp b/src/platform/ASR/ConnectivityManagerImpl.cpp new file mode 100644 index 00000000000000..6e828c897f1e19 --- /dev/null +++ b/src/platform/ASR/ConnectivityManagerImpl.cpp @@ -0,0 +1,646 @@ +/* + * + * Copyright (c) 2021 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. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include + +#include + +#if INET_CONFIG_ENABLE_TCP_ENDPOINT +#include +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lwip/opt.h" +#include +// asr wifi +#include "lega_wlan_api.h" +#if !CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +#error "WiFi Station support must be enabled when building for ASR" +#endif + +using namespace ::chip; +using namespace ::chip::Inet; +using namespace ::chip::System; +using namespace ::chip::TLV; +#ifdef __cplusplus +extern "C" { +#endif +extern struct netif * lwip_get_netif(void); +#ifdef __cplusplus +} +#endif +namespace chip { +namespace DeviceLayer { + +ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; + +ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode(void) +{ + mWiFiStationMode = kWiFiStationMode_Enabled; + return mWiFiStationMode; +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + VerifyOrExit(val != kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (val != kWiFiStationMode_ApplicationControlled) + { + ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode), + WiFiStationModeToStr(val)); + mWiFiStationMode = val; + /* Schedule work for disabled case causes station mode not getting enabled */ + if (mWiFiStationMode != kWiFiStationMode_Disabled) + { + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); + } + else + { + /* Call Drive Station directly to disable directly instead of scheduling */ + DriveStationState(); + } + } + +exit: + return err; +} + +bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void) +{ + return GetWiFiStationMode() == kWiFiStationMode_Enabled; +} + +bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void) +{ + return Internal::ASRUtils::IsStationProvisioned(); +} + +void ConnectivityManagerImpl::_ClearWiFiStationProvision(void) +{ + if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) + { + lega_wlan_wifi_conf stationConfig; + + memset(&stationConfig, 0, sizeof(stationConfig)); + Internal::ASRUtils::asr_wifi_set_config(&stationConfig); + + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + } +} + +CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT); + + if (mWiFiAPMode != val) + { + ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val)); + } + mWiFiAPMode = val; + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); +exit: + return err; +} + +void ConnectivityManagerImpl::_DemandStartWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + mLastAPDemandTime = System::SystemClock().GetMonotonicTimestamp(); + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + } +} + +void ConnectivityManagerImpl::_StopOnDemandWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + mLastAPDemandTime = System::Clock::kZero; + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); + } +} + +void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP(void) +{ + if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) + { + if (mWiFiAPState == kWiFiAPState_Activating || mWiFiAPState == kWiFiAPState_Active) + { + mLastAPDemandTime = System::SystemClock().GetMonotonicTimestamp(); + } + } +} + +void ConnectivityManagerImpl::_SetWiFiAPIdleTimeout(System::Clock::Timeout val) +{ + mWiFiAPIdleTimeout = val; + DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, NULL); +} + +CHIP_ERROR ConnectivityManagerImpl::_GetAndLogWifiStatsCounters(void) +{ + ChipLogProgress(DeviceLayer, "ConnectivityManagerImpl::_GetAndLogWifiStatsCounters"); + return CHIP_NO_ERROR; +} + +// ==================== ConnectivityManager Platform Internal Methods ==================== +CHIP_ERROR ConnectivityManagerImpl::_Init() +{ + ChipLogProgress(DeviceLayer, "ConnectivityManagerImpl::_Init"); + CHIP_ERROR err = CHIP_NO_ERROR; + mLastStationConnectFailTime = System::Clock::kZero; + mLastAPDemandTime = System::Clock::kZero; + mWiFiStationMode = kWiFiStationMode_Disabled; + mWiFiStationState = kWiFiStationState_NotConnected; + mWiFiAPMode = kWiFiAPMode_Disabled; + mWiFiAPState = kWiFiAPState_NotActive; + mWiFiStationReconnectInterval = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL); + mWiFiAPIdleTimeout = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT); + mFlags.SetRaw(0); + + // Ensure that ASR station mode is enabled. + err = Internal::ASRUtils::EnableStationMode(); + SuccessOrExit(err); + err = Internal::ASRUtils::SetStationConnected(false); + SuccessOrExit(err); + + // If there is no persistent station provision... + if (!IsWiFiStationProvisioned()) + { + ReturnErrorOnFailure(SetWiFiStationMode(kWiFiStationMode_Enabled)); + } + else + { + // Enable WiFi station mode. + ReturnErrorOnFailure(SetWiFiStationMode(kWiFiStationMode_Enabled)); + } + // Queue work items to bootstrap the station state machines once the Chip event loop is running. + err = DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); +exit: + return err; +} + +void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) {} + +void ConnectivityManagerImpl::_OnWiFiScanDone() +{ + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); +} + +void ConnectivityManagerImpl::_OnWiFiStationProvisionChange() +{ + DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); +} + +void ConnectivityManagerImpl::DriveStationState(::chip::System::Layer * aLayer, void * aAppState) +{ + sInstance.DriveStationState(); +} + +void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState) +{ + sInstance.DriveAPState(); +} + +void ConnectivityManagerImpl::ChangeWiFiStationState(WiFiStationState newState) +{ + if (mWiFiStationState != newState) + { + ChipLogProgress(DeviceLayer, "WiFi station state change: %s -> %s", WiFiStationStateToStr(mWiFiStationState), + WiFiStationStateToStr(newState)); + mWiFiStationState = newState; + SystemLayer().ScheduleLambda([]() { NetworkCommissioning::ASRWiFiDriver::GetInstance().OnNetworkStatusChange(); }); + } +} + +void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState) +{ + if (mWiFiAPState != newState) + { + ChipLogProgress(DeviceLayer, "WiFi AP state change: %s -> %s", WiFiAPStateToStr(mWiFiAPState), WiFiAPStateToStr(newState)); + mWiFiAPState = newState; + } +} + +CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() +{ + ChipLogProgress(DeviceLayer, "ConnectivityManagerImpl::ConfigureWiFiAP"); + return CHIP_NO_ERROR; +} + +void ConnectivityManagerImpl::DriveAPState() {} + +void ConnectivityManagerImpl::DriveStationState() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + bool stationConnected; + + // If the station interface is NOT under application control... + if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) + { + err = WiFi_init(); + SuccessOrExit(err); + // Ensure that station mode is enabled in the ASR WiFi layer. + err = Internal::ASRUtils::EnableStationMode(); + SuccessOrExit(err); + } + + // Determine if the ASR WiFi layer thinks the station interface is currently connected. + err = Internal::ASRUtils::IsStationConnected(stationConnected); + SuccessOrExit(err); + // If the station interface is currently connected ... + if (stationConnected) + { + // Advance the station state to Connected if it was previously NotConnected or + // a previously initiated connect attempt succeeded. + if (mWiFiStationState == kWiFiStationState_NotConnected || mWiFiStationState == kWiFiStationState_Connecting_Succeeded) + { + ChangeWiFiStationState(kWiFiStationState_Connected); + ChipLogProgress(DeviceLayer, "WiFi station interface connected"); + mLastStationConnectFailTime = System::Clock::kZero; + OnStationConnected(); + } + + // If the WiFi station interface is no longer enabled, or no longer provisioned, + // disconnect the station from the AP, unless the WiFi station mode is currently + // under application control. + if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled && + (mWiFiStationMode != kWiFiStationMode_Enabled || !IsWiFiStationProvisioned())) + { + ChipLogProgress(DeviceLayer, "Disconnecting WiFi station interface"); + err = Internal::ASRUtils::asr_wifi_disconnect(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "asr_wifi_disconnect() failed: %s", chip::ErrorStr(err)); + } + SuccessOrExit(err); + + ChangeWiFiStationState(kWiFiStationState_Disconnecting); + } + } + // Otherwise the station interface is NOT connected to an AP, so... + else + { + System::Clock::Timestamp now = System::SystemClock().GetMonotonicTimestamp(); + + // Advance the station state to NotConnected if it was previously Connected or Disconnecting, + // or if a previous initiated connect attempt failed. + if (mWiFiStationState == kWiFiStationState_Connected || mWiFiStationState == kWiFiStationState_Disconnecting || + mWiFiStationState == kWiFiStationState_Connecting_Failed) + { + WiFiStationState prevState = mWiFiStationState; + ChangeWiFiStationState(kWiFiStationState_NotConnected); + if (prevState != kWiFiStationState_Connecting_Failed) + { + ChipLogProgress(DeviceLayer, "WiFi station interface disconnected"); + mLastStationConnectFailTime = System::Clock::kZero; + OnStationDisconnected(); + } + else + { + mLastStationConnectFailTime = now; + } + } + // If the WiFi station interface is now enabled and provisioned (and by implication, + // not presently under application control), AND the system is not in the process of + // scanning, then... + if (mWiFiStationMode == kWiFiStationMode_Enabled && IsWiFiStationProvisioned()) + { + // Initiate a connection to the AP if we haven't done so before, or if enough + // time has passed since the last attempt. + if (mLastStationConnectFailTime == System::Clock::kZero || + now >= mLastStationConnectFailTime + mWiFiStationReconnectInterval) + { + if (mWiFiStationState != kWiFiStationState_Connecting) + { + ChipLogProgress(DeviceLayer, "Attempting to connect WiFi station interface"); + err = Internal::ASRUtils::asr_wifi_connect(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "asr_wifi_connect() failed: %s", chip::ErrorStr(err)); + } + SuccessOrExit(err); + ChangeWiFiStationState(kWiFiStationState_Connecting); + } + } + + // Otherwise arrange another connection attempt at a suitable point in the future. + else + { + System::Clock::Timeout timeToNextConnect = (mLastStationConnectFailTime + mWiFiStationReconnectInterval) - now; + ChipLogProgress(DeviceLayer, "Next WiFi station reconnect in %" PRIu32 " ms ", + System::Clock::Milliseconds32(timeToNextConnect).count()); + + err = DeviceLayer::SystemLayer().StartTimer(timeToNextConnect, DriveStationState, NULL); + SuccessOrExit(err); + } + } + } + +exit: + + ChipLogProgress(DeviceLayer, "Done driving station state, nothing else to do..."); + // Kick-off any pending network scan that might have been deferred due to the activity + // of the WiFi station. +} + +void ConnectivityManagerImpl::OnStationConnected() +{ + NetworkCommissioning::ASRWiFiDriver::GetInstance().OnConnectWiFiNetwork(); + // TODO Invoke WARM to perform actions that occur when the WiFi station interface comes up. + + // Alert other components of the new state. + ChipDeviceEvent event; + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Established; + PlatformMgr().PostEventOrDie(&event); + WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); + + if (delegate) + { + delegate->OnConnectionStatusChanged( + chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kConnected)); + } + + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::OnStationDisconnected() +{ + // TODO Invoke WARM to perform actions that occur when the WiFi station interface goes down. + + // Alert other components of the new state. + ChipDeviceEvent event; + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Lost; + PlatformMgr().PostEventOrDie(&event); + WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); + uint16_t reason = NetworkCommissioning::ASRWiFiDriver::GetInstance().GetLastDisconnectReason(); + uint8_t associationFailureCause = + chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kUnknown); + + if (delegate) + { + switch (reason) + { + case WLAN_STA_MODE_BEACON_LOSS: + case WLAN_STA_MODE_NO_AP_FOUND: + associationFailureCause = + chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kSsidNotFound); + delegate->OnAssociationFailureDetected(associationFailureCause, reason); + break; + case WLAN_STA_MODE_ASSOC_FAIL: + associationFailureCause = + chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kAssociationFailed); + delegate->OnAssociationFailureDetected(associationFailureCause, reason); + break; + case WLAN_STA_MODE_AUTH_FAIL: + case WLAN_STA_MODE_PASSWORD_ERR: + associationFailureCause = chip::to_underlying( + chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kAuthenticationFailed); + delegate->OnAssociationFailureDetected(associationFailureCause, reason); + break; + case WLAN_STA_MODE_DHCP_FAIL: + case WLAN_STA_MODE_CONN_RETRY_MAX: + break; + + default: + delegate->OnAssociationFailureDetected(associationFailureCause, reason); + break; + } + delegate->OnDisconnectionDetected(reason); + delegate->OnConnectionStatusChanged( + chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kNotConnected)); + } + + UpdateInternetConnectivityState(); +} + +void ConnectivityManagerImpl::UpdateInternetConnectivityState(void) +{ + bool haveIPv4Conn = false; + bool haveIPv6Conn = false; + const bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity); + const bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity); + struct netif * net_interface = NULL; + IPAddress addr; + + ChipLogProgress(DeviceLayer, "UpdateInternetConnectivityState"); + // If the WiFi station is currently in the connected state... + if (mWiFiStationState == kWiFiStationState_Connected) + { + net_interface = lwip_get_netif(); + if (net_interface != NULL && netif_is_up(net_interface) && netif_is_link_up(net_interface)) + { + // Check if a DNS server is currently configured. If so... + ip_addr_t dnsServerAddr = *dns_getserver(0); + if (!ip_addr_isany_val(dnsServerAddr)) + { + if (!ip4_addr_isany_val(*netif_ip4_addr(net_interface)) && !ip4_addr_isany_val(*netif_ip4_gw(net_interface))) + { + haveIPv4Conn = true; + char addrStr[INET_ADDRSTRLEN]; + ip4addr_ntoa_r(netif_ip4_addr(net_interface), addrStr, sizeof(addrStr)); + + // ChipLogProgress(DeviceLayer, "IPv4 Address Assigned : %s", ip4addr_ntoa(netif_ip4_addr(net_interface))); + + IPAddress::FromString(addrStr, addr); + } + // Search among the IPv6 addresses assigned to the interface for a Global Unicast + // address (2000::/3) that is in the valid state. If such an address is found... + for (uint8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) + { + if (ip6_addr_isglobal(netif_ip6_addr(net_interface, i)) && + ip6_addr_isvalid(netif_ip6_addr_state(net_interface, i))) + { + // Determine if there is a default IPv6 router that is currently reachable + // via the station interface. If so, presume for now that the device has + // IPv6 connectivity. + struct netif * found_if = nd6_find_route(IP6_ADDR_ANY6); + if (found_if && net_interface->num == found_if->num) + { + haveIPv6Conn = true; + // ChipLogProgress(DeviceLayer, "IPv6 Address Assigned : %s", ip6addr_ntoa(netif_ip6_addr(net_interface, + // i))); + } + } + } + } + } + } + // If the internet connectivity state has changed... + if (haveIPv4Conn != hadIPv4Conn || haveIPv6Conn != hadIPv6Conn) + { + // Update the current state. + mFlags.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity, haveIPv4Conn) + .Set(ConnectivityFlags::kHaveIPv6InternetConnectivity, haveIPv6Conn); + + // Alert other components of the state change. + ChipDeviceEvent event; + event.Type = DeviceEventType::kInternetConnectivityChange; + event.InternetConnectivityChange.IPv4 = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn); + event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn); + event.InternetConnectivityChange.ipAddress = addr; + + PlatformMgr().PostEventOrDie(&event); + + if (haveIPv4Conn != hadIPv4Conn) + { + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST"); + } + + if (haveIPv6Conn != hadIPv6Conn) + { + ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST"); + } + } +} + +void ConnectivityManagerImpl::lega_wifi_connect_state(lega_wifi_event_e stat) +{ + switch (stat) + { + case EVENT_STATION_UP: + ChipLogProgress(DeviceLayer, "wifi_connect_done"); + Internal::ASRUtils::SetStationConnected(true); + if (ConnectivityMgrImpl().mWiFiStationState == kWiFiStationState_Connecting) + { + ConnectivityMgrImpl().ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded); + } + ConnectivityMgrImpl().DriveStationState(); + break; + case EVENT_STATION_DOWN: + ChipLogProgress(DeviceLayer, "wifi_disconnect_done"); + Internal::ASRUtils::SetStationConnected(false); + if (ConnectivityMgrImpl().mWiFiStationState == kWiFiStationState_Connecting) + { + ConnectivityMgrImpl().ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); + } + ConnectivityMgrImpl().DriveStationState(); + break; + case EVENT_AP_UP: + ChipLogProgress(DeviceLayer, "wifi_softap_open_done"); + break; + case EVENT_AP_DOWN: + ChipLogProgress(DeviceLayer, "wifi_softap_close_done"); + break; + case EVENT_STA_CLOSE: + ChipLogProgress(DeviceLayer, "wifi_sta_close_done"); + Internal::ASRUtils::SetStationConnected(false); + ConnectivityMgrImpl().ChangeWiFiStationState(kWiFiStationState_NotConnected); + NetworkCommissioning::ASRWiFiDriver::GetInstance().SetLastDisconnectReason(0); + ConnectivityMgrImpl().DriveStationState(); + break; + default: + ChipLogProgress(DeviceLayer, "unsupport wifi_event_e"); + break; + } +} + +void ConnectivityManagerImpl::lega_wifi_scan_ind(lega_wlan_scan_result_t * result) +{ + NetworkCommissioning::ASRWiFiDriver::GetInstance().OnScanWiFiNetworkDone(result); +} + +void ConnectivityManagerImpl::lega_wifi_get_ip_ind(lega_wlan_ip_stat_t * pnet) +{ + ChipLogProgress(DeviceLayer, "Got ip : %s, gw : %s, mask : %s, mac : %s", pnet->ip, pnet->gate, pnet->mask, pnet->macaddr); + + ConnectivityMgrImpl().UpdateInternetConnectivityState(); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Assigned; + PlatformMgr().PostEventOrDie(&event); +} + +void ConnectivityManagerImpl::lega_wifi_get_ip6_ind(lega_wlan_ip_stat_t * pnet) +{ + int i = 0; + int preferred_ip6 = 0; + for (i = 0; i < 3; i++) + { + if (pnet->ip6[i].state == 0x30) /* IP6_ADDR_PREFERRED */ + { + ChipLogProgress(DeviceLayer, "Got ip v6 #%d : %s", i, pnet->ip6[i].addr); + preferred_ip6++; + } + } + if (preferred_ip6) + { + ConnectivityMgrImpl().UpdateInternetConnectivityState(); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kInterfaceIpAddressChanged; + event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV6_Assigned; + PlatformMgr().PostEventOrDie(&event); + } +} + +void ConnectivityManagerImpl::lega_wifi_ap_peer_change(lega_wlan_client_addr_info_t * peer_info, uint8_t connect) {} + +void ConnectivityManagerImpl::lega_wlan_err_stat_handler(lega_wlan_err_status_e err_info) +{ + ChipLogProgress(DeviceLayer, "lega wlan err stat:%d", err_info); + if (ConnectivityMgrImpl().mWiFiStationState == kWiFiStationState_Connecting) + { + ConnectivityMgrImpl().ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); + } + NetworkCommissioning::ASRWiFiDriver::GetInstance().SetLastDisconnectReason(err_info); + ConnectivityMgrImpl().DriveStationState(); +} + +CHIP_ERROR ConnectivityManagerImpl::WiFi_init(void) +{ + lega_wlan_scan_compeleted_cb_register(ConnectivityManagerImpl::lega_wifi_scan_ind); + lega_wlan_stat_chg_cb_register(ConnectivityManagerImpl::lega_wifi_connect_state); + lega_wlan_ip_got_cb_register(ConnectivityManagerImpl::lega_wifi_get_ip_ind); + lega_wlan_ip6_got_cb_register(ConnectivityManagerImpl::lega_wifi_get_ip6_ind); + lega_wlan_ap_peer_change_cb_register(ConnectivityManagerImpl::lega_wifi_ap_peer_change); + lega_wlan_err_stat_cb_register(ConnectivityManagerImpl::lega_wlan_err_stat_handler); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::ping_thread() +{ + return CHIP_NO_ERROR; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/ConnectivityManagerImpl.h b/src/platform/ASR/ConnectivityManagerImpl.h new file mode 100644 index 00000000000000..8d4d5460e97b2f --- /dev/null +++ b/src/platform/ASR/ConnectivityManagerImpl.h @@ -0,0 +1,207 @@ +/* + * + * Copyright (c) 2021 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 + +#include +#include +#include +#if INET_CONFIG_ENABLE_TCP_ENDPOINT +#include +#endif +#include +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +#include +#else +#include +#endif +#include + +#include "lega_wlan_api.h" +#include +#include + +namespace Inet { +class IPAddress; +} // namespace Inet + +namespace chip { +namespace DeviceLayer { + +class PlatformManagerImpl; + +/** + * Concrete implementation of the ConnectivityManager singleton object for the ASR platform. + */ +class ConnectivityManagerImpl final : public ConnectivityManager, + public Internal::GenericConnectivityManagerImpl, + public Internal::GenericConnectivityManagerImpl_UDP, +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + public Internal::GenericConnectivityManagerImpl_TCP, +#endif + public Internal::GenericConnectivityManagerImpl_WiFi, +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + public Internal::GenericConnectivityManagerImpl_BLE, +#else + public Internal::GenericConnectivityManagerImpl_NoBLE, +#endif + public Internal::GenericConnectivityManagerImpl_NoThread +{ + + // Allow the ConnectivityManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class ConnectivityManager; + +public: + CHIP_ERROR ping_thread(void); + +private: + using Flags = GenericConnectivityManagerImpl_WiFi::ConnectivityFlags; + // ===== Members that implement the ConnectivityManager abstract interface. + + WiFiStationMode _GetWiFiStationMode(void); + CHIP_ERROR _SetWiFiStationMode(WiFiStationMode val); + bool _IsWiFiStationEnabled(void); + bool _IsWiFiStationApplicationControlled(void); + bool _IsWiFiStationConnected(void); + System::Clock::Timeout _GetWiFiStationReconnectInterval(void); + CHIP_ERROR _SetWiFiStationReconnectInterval(System::Clock::Timeout val); + bool _IsWiFiStationProvisioned(void); + void _ClearWiFiStationProvision(void); + CHIP_ERROR _GetAndLogWifiStatsCounters(void); + void ChangeWiFiStationState(WiFiStationState newState); + WiFiAPMode _GetWiFiAPMode(void); + CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val); + bool _IsWiFiAPActive(void); + bool _IsWiFiAPApplicationControlled(void); + void _DemandStartWiFiAP(void); + void _StopOnDemandWiFiAP(void); + void _MaintainOnDemandWiFiAP(void); + System::Clock::Timeout _GetWiFiAPIdleTimeout(void); + void _SetWiFiAPIdleTimeout(System::Clock::Timeout val); + + // Service connectivity methods + + CHIP_ERROR _Init(void); + void _OnPlatformEvent(const ChipDeviceEvent * event); + bool _CanStartWiFiScan(); + void _OnWiFiScanDone(); + void _OnWiFiStationProvisionChange(); + + // ===== Members for internal use by the following friends. + + friend ConnectivityManager & ConnectivityMgr(void); + friend ConnectivityManagerImpl & ConnectivityMgrImpl(void); + + static ConnectivityManagerImpl sInstance; + + // ===== Private members reserved for use by this class only. + System::Clock::Timestamp mLastStationConnectFailTime; + System::Clock::Timestamp mLastAPDemandTime; + WiFiStationMode mWiFiStationMode; + WiFiStationState mWiFiStationState; + WiFiAPMode mWiFiAPMode; + WiFiAPState mWiFiAPState; + System::Clock::Timeout mWiFiStationReconnectInterval; + System::Clock::Timeout mWiFiAPIdleTimeout; + BitFlags mFlags; + bool eventcallback; + + static void DriveStationState(::chip::System::Layer * aLayer, void * aAppState); + static void DriveAPState(::chip::System::Layer * aLayer, void * aAppState); + void DriveStationState(void); + void OnStationConnected(void); + void OnStationDisconnected(void); + void DriveAPState(void); + CHIP_ERROR ConfigureWiFiAP(void); + void ChangeWiFiAPState(WiFiAPState newState); + void UpdateInternetConnectivityState(void); + static void lega_wifi_scan_ind(lega_wlan_scan_result_t * result); + static void lega_wifi_connect_state(lega_wifi_event_e stat); + static void lega_wifi_get_ip_ind(lega_wlan_ip_stat_t * pnet); + static void lega_wifi_get_ip6_ind(lega_wlan_ip_stat_t * pnet); + static void lega_wifi_ap_peer_change(lega_wlan_client_addr_info_t * peer_info, uint8_t connect); + static void lega_wlan_err_stat_handler(lega_wlan_err_status_e err_info); + CHIP_ERROR WiFi_init(void); +}; + +inline bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled(void) +{ + return mWiFiStationMode == kWiFiStationMode_ApplicationControlled; +} + +inline bool ConnectivityManagerImpl::_IsWiFiStationConnected(void) +{ + return mWiFiStationState == kWiFiStationState_Connected; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPApplicationControlled(void) +{ + return mWiFiAPMode == kWiFiAPMode_ApplicationControlled; +} + +inline System::Clock::Timeout ConnectivityManagerImpl::_GetWiFiStationReconnectInterval(void) +{ + return mWiFiStationReconnectInterval; +} + +inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode(void) +{ + return mWiFiAPMode; +} + +inline bool ConnectivityManagerImpl::_IsWiFiAPActive(void) +{ + return mWiFiAPState == kWiFiAPState_Active; +} + +inline System::Clock::Timeout ConnectivityManagerImpl::_GetWiFiAPIdleTimeout(void) +{ + return mWiFiAPIdleTimeout; +} + +inline bool ConnectivityManagerImpl::_CanStartWiFiScan() +{ + return mWiFiStationState != kWiFiStationState_Connecting; +} + +/** + * Returns the public interface of the ConnectivityManager singleton object. + * + * Chip applications should use this to access features of the ConnectivityManager object + * that are common to all platforms. + */ +inline ConnectivityManager & ConnectivityMgr(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the ConnectivityManager singleton object. + * + * Chip applications can use this to gain access to features of the ConnectivityManager + * that are specific to the ASR platform. + */ +inline ConnectivityManagerImpl & ConnectivityMgrImpl(void) +{ + return ConnectivityManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/DiagnosticDataProviderImpl.cpp b/src/platform/ASR/DiagnosticDataProviderImpl.cpp new file mode 100644 index 00000000000000..cc311958cf3636 --- /dev/null +++ b/src/platform/ASR/DiagnosticDataProviderImpl.cpp @@ -0,0 +1,351 @@ +/* + * + * 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 +#include +#include +#include +#include + +#ifdef CFG_PLF_RV32 +#include "asr_alto_boot.h" +#define duet_get_boot_type asr_get_boot_type +#else +#include "duet_boot.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif +extern struct netif * lwip_get_netif(void); +#ifdef __cplusplus +} +#endif + +namespace chip { +namespace DeviceLayer { + +DiagnosticDataProviderImpl & DiagnosticDataProviderImpl::GetDefaultInstance() +{ + static DiagnosticDataProviderImpl sInstance; + return sInstance; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapFree(uint64_t & currentHeapFree) +{ + currentHeapFree = static_cast(lega_rtos_get_free_heap_size()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapUsed(uint64_t & currentHeapUsed) +{ + currentHeapUsed = static_cast(lega_rtos_get_total_size() - lega_rtos_get_free_heap_size()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) +{ + currentHeapHighWatermark = static_cast(lega_rtos_get_total_size() - lega_rtos_get_minimum_free_heap_size()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount) +{ + uint32_t count = 0; + + CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count); + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(count <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + rebootCount = static_cast(count); + } + + return err; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime) +{ + System::Clock::Timestamp currentTime = System::SystemClock().GetMonotonicTimestamp(); + System::Clock::Timestamp startTime = PlatformMgrImpl().GetStartTime(); + + if (currentTime >= startTime) + { + upTime = std::chrono::duration_cast(currentTime - startTime).count(); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_INVALID_TIME; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + uint64_t upTime = 0; + + if (GetUpTime(upTime) == CHIP_NO_ERROR) + { + uint32_t totalHours = 0; + if (ConfigurationMgr().GetTotalOperationalHours(totalHours) == CHIP_NO_ERROR) + { + /* uptime is terms of seconds and dividing it by 3600 to calculate + * totalOperationalHours in hours. + */ + VerifyOrReturnError(upTime / 3600 <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + totalOperationalHours = totalHours + static_cast(upTime / 3600); + return CHIP_NO_ERROR; + } + } + + return CHIP_ERROR_INVALID_TIME; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(BootReasonType & bootReason) +{ + uint32_t reason = duet_get_boot_type(); + + bootReason = BootReasonType::kUnspecified; + + if (reason == UNKNOWN_RST) + { + bootReason = BootReasonType::kUnspecified; + } + else if (reason == PWR_ON_RST) + { + bootReason = BootReasonType::kPowerOnReboot; + } + else if (reason == HARDWARE_PIN_RST) + { + bootReason = BootReasonType::kBrownOutReset; + } + else if (reason == SOFTWARE_RST) + { + bootReason = BootReasonType::kSoftwareReset; + } + /* + else if (reason == WDG_RST) + { + bootReason = BootReasonType::kSoftwareWatchdogReset; + } + */ + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp) +{ + NetworkInterface * ifp = new NetworkInterface(); + struct netif * ifa; + + ifa = lwip_get_netif(); + + if (ifa == NULL) + { + ChipLogError(DeviceLayer, "Failed to get network interfaces"); + } + else + { + Platform::CopyString(ifp->Name, ifa->name); + + ifp->name = CharSpan::fromCharString(ifp->Name); + ifp->isOperational = true; + if ((ifa->flags) & NETIF_FLAG_ETHERNET) + ifp->type = EMBER_ZCL_INTERFACE_TYPE_ENUM_ETHERNET; + else + ifp->type = EMBER_ZCL_INTERFACE_TYPE_ENUM_WI_FI; + ifp->offPremiseServicesReachableIPv4.SetNull(); + ifp->offPremiseServicesReachableIPv6.SetNull(); + + memcpy(ifp->MacAddress, ifa->hwaddr, sizeof(ifa->hwaddr)); + + if (0) + { + ChipLogError(DeviceLayer, "Failed to get network hardware address"); + } + else + { + // Set 48-bit IEEE MAC Address + ifp->hardwareAddress = ByteSpan(ifp->MacAddress, 6); + } + + if (ifa->ip_addr.u_addr.ip4.addr != 0) + { + memcpy(ifp->Ipv4AddressesBuffer[0], &(ifa->ip_addr.u_addr.ip4.addr), kMaxIPv4AddrSize); + ifp->Ipv4AddressSpans[0] = ByteSpan(ifp->Ipv4AddressesBuffer[0], kMaxIPv4AddrSize); + ifp->IPv4Addresses = chip::app::DataModel::List(ifp->Ipv4AddressSpans, 1); + } + + if (ifa->ip6_addr->u_addr.ip6.addr != 0) + { + memcpy(ifp->Ipv6AddressesBuffer[0], &(ifa->ip6_addr->u_addr.ip6.addr), kMaxIPv6AddrSize); + ifp->Ipv6AddressSpans[0] = ByteSpan(ifp->Ipv6AddressesBuffer[0], kMaxIPv6AddrSize); + ifp->IPv6Addresses = chip::app::DataModel::List(ifp->Ipv6AddressSpans, 1); + } + } + + *netifpp = ifp; + return CHIP_NO_ERROR; +} + +void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp) +{ + while (netifp) + { + NetworkInterface * del = netifp; + netifp = netifp->Next; + delete del; + } +} + +/* Wi-Fi Diagnostics Cluster Support */ + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBssId(MutableByteSpan & BssId) +{ + constexpr size_t bssIdSize = 6; + VerifyOrReturnError(BssId.size() >= bssIdSize, CHIP_ERROR_BUFFER_TOO_SMALL); + + lega_wlan_link_stat_t link_stat; + + if (lega_wlan_get_link_status(&link_stat) == 0) + { + memcpy(BssId.data(), link_stat.bssid, bssIdSize); + BssId.reduce_size(bssIdSize); + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiSecurityType(app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum & securityType) +{ + using app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum; + + lega_wlan_ap_info_adv_t * apinfo = lega_wlan_get_associated_apinfo(); + + switch (apinfo->security) + { + case WLAN_SECURITY_OPEN: + securityType = SecurityTypeEnum::kNone; + break; + case WLAN_SECURITY_WEP: + securityType = SecurityTypeEnum::kWep; + break; + case WLAN_SECURITY_WPA: + securityType = SecurityTypeEnum::kWpa; + break; + case WLAN_SECURITY_WPA2: + case WLAN_SECURITY_AUTO: + securityType = SecurityTypeEnum::kWpa2; + break; + default: + securityType = SecurityTypeEnum::kUnspecified; + break; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiVersion(app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum & wifiVersion) +{ + // Support 802.11a/n Wi-Fi in Beken chipset + // TODO: https://github.com/project-chip/connectedhomeip/issues/25543 + wifiVersion = app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum::kN; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiChannelNumber(uint16_t & channelNumber) +{ + lega_wlan_link_stat_t link_stat; + channelNumber = 0; + + if (lega_wlan_get_link_status(&link_stat) == 0) + { + channelNumber = link_stat.channel; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiRssi(int8_t & rssi) +{ + lega_wlan_link_stat_t link_stat; + rssi = 0; + + if (lega_wlan_get_link_status(&link_stat) == 0) + { + rssi = link_stat.wifi_strength; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconRxCount(uint32_t & beaconRxCount) +{ + beaconRxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconLostCount(uint32_t & beaconLostCount) +{ + beaconLostCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) +{ + currentMaxRate = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) +{ + packetMulticastRxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) +{ + packetMulticastTxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) +{ + packetUnicastRxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) +{ + packetUnicastTxCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiOverrunCount(uint64_t & overrunCount) +{ + overrunCount = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR DiagnosticDataProviderImpl::ResetWiFiNetworkDiagnosticsCounts() +{ + return CHIP_NO_ERROR; +} + +DiagnosticDataProvider & GetDiagnosticDataProviderImpl() +{ + return DiagnosticDataProviderImpl::GetDefaultInstance(); +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/DiagnosticDataProviderImpl.h b/src/platform/ASR/DiagnosticDataProviderImpl.h new file mode 100644 index 00000000000000..b60aa27b57ec93 --- /dev/null +++ b/src/platform/ASR/DiagnosticDataProviderImpl.h @@ -0,0 +1,89 @@ +/* + * + * 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 + +#include + +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for Linux platforms. + */ +class DiagnosticDataProviderImpl : public DiagnosticDataProvider +{ +public: + static DiagnosticDataProviderImpl & GetDefaultInstance(); + + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override; + CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override; + CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override; + + CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override; + CHIP_ERROR GetUpTime(uint64_t & upTime) override; + CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override; + CHIP_ERROR GetBootReason(BootReasonType & bootReason) override; + CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override; + void ReleaseNetworkInterfaces(NetworkInterface * netifp) override; + + CHIP_ERROR GetWiFiBssId(MutableByteSpan & BssId) override; + CHIP_ERROR GetWiFiSecurityType(app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum & securityType) override; + CHIP_ERROR GetWiFiVersion(app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum & wifiVersion) override; + CHIP_ERROR GetWiFiChannelNumber(uint16_t & channelNumber) override; + CHIP_ERROR GetWiFiRssi(int8_t & rssi) override; + CHIP_ERROR GetWiFiBeaconRxCount(uint32_t & beaconRxCount) override; + CHIP_ERROR GetWiFiBeaconLostCount(uint32_t & beaconLostCount) override; + CHIP_ERROR GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) override; + CHIP_ERROR GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) override; + CHIP_ERROR GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) override; + CHIP_ERROR GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) override; + CHIP_ERROR GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) override; + CHIP_ERROR GetWiFiOverrunCount(uint64_t & overrunCount) override; + CHIP_ERROR ResetWiFiNetworkDiagnosticsCounts() override; + /* These variables will be set to 0 during start up and will be updated when reset-counts + * zcl command is received. + * These are considered as base for below attributes of WiFi Diagnostics Cluster: + * BeaconLostCount, BeaconRxCount, PacketMulticastRxCount, PacketMulticastTxCount, + * PacketUnicastRxCount, PacketUnicastTxCount, OverrunCount. + * Each attributes read will be difference of WLAN counters minus equivalent variables below. + */ + uint32_t mBeaconRxCount = 0; + uint32_t mBeaconLostCount = 0; + uint32_t mPacketMulticastRxCount = 0; + uint32_t mPacketMulticastTxCount = 0; + uint32_t mPacketUnicastRxCount = 0; + uint32_t mPacketUnicastTxCount = 0; + uint64_t mOverrunCount = 0; + bool mipv4_offpremise = false; + bool mipv6_offpremise = false; +}; + +/** + * Returns the platform-specific implementation of the DiagnosticDataProvider singleton object. + * + * Applications can use this to gain access to features of the DiagnosticDataProvider + * that are specific to the selected platform. + */ +DiagnosticDataProvider & GetDiagnosticDataProviderImpl(); + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/InetPlatformConfig.h b/src/platform/ASR/InetPlatformConfig.h new file mode 100755 index 00000000000000..6858e9a710daff --- /dev/null +++ b/src/platform/ASR/InetPlatformConfig.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 2021 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 + +// ==================== Platform Adaptations ==================== + +#define INET_CONFIG_ERROR_TYPE uint32_t +#define INET_CONFIG_NO_ERROR 0 +#define INET_CONFIG_ERROR_MIN 1000000 +#define INET_CONFIG_ERROR_MAX 1000999 + +// ==================== General Configuration Overrides ==================== + +#ifndef INET_CONFIG_NUM_TCP_ENDPOINTS +#define INET_CONFIG_NUM_TCP_ENDPOINTS 10 +#endif // INET_CONFIG_NUM_TCP_ENDPOINTS + +#ifndef INET_CONFIG_NUM_UDP_ENDPOINTS +#define INET_CONFIG_NUM_UDP_ENDPOINTS 20 +#endif // INET_CONFIG_NUM_UDP_ENDPOINTS diff --git a/src/platform/ASR/KeyValueStoreManagerImpl.cpp b/src/platform/ASR/KeyValueStoreManagerImpl.cpp new file mode 100644 index 00000000000000..bc499ae3a046fd --- /dev/null +++ b/src/platform/ASR/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,119 @@ +/* + * + * 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 +#ifdef CFG_PLF_RV32 +#include "alto_flash_kv.h" +#include "asr_flash.h" +#include "asr_rv32.h" +#define duet_flash_kv_set alto_flash_kv_set +#define duet_flash_kv_get alto_flash_kv_get +#define duet_flash_kv_del alto_flash_kv_del +#define duet_flash_erase asr_flash_erase +#else +#include "duet_cm4.h" +#include "duet_flash.h" +#include "duet_flash_kv.h" +#endif +#include "string.h" + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +CHIP_ERROR KeyValueStoreManagerImpl::Init() +{ + // duet_flash_kv_init(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR KeyValueStoreManagerImpl::ConvertKVResultToChip(int32_t err) const +{ + switch (err) + { + case 0: /* Successed */ + return CHIP_NO_ERROR; + case -10002: /* The parameter is invalid */ + return CHIP_ERROR_INVALID_ARGUMENT; + case -10001: /* The space is out of range */ + case -10003: /* The os memory malloc error */ + return CHIP_ERROR_BUFFER_TOO_SMALL; + case -10005: /* The flash read operation error */ + case -10006: /* The flash write operation error */ + case -10007: /* The flash erase operation error */ + return CHIP_ERROR_INTEGRITY_CHECK_FAILED; + case -10004: /* Could not found the item */ + return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + default: + return CHIP_ERROR_INTERNAL; + } + return CHIP_ERROR_INTERNAL; +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size, + size_t offset_bytes) const +{ + int32_t ret = 0; + int32_t buffer_len = value_size; + ret = duet_flash_kv_get(key, value, (int32_t *) &buffer_len); + if (ret == 0) + { + if (read_bytes_size) + { + *read_bytes_size = buffer_len; + } + } + + return ConvertKVResultToChip(ret); +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size) +{ + int32_t ret = 0; + ret = duet_flash_kv_set(key, value, value_size, 1); + + return ConvertKVResultToChip(ret); +} + +CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key) +{ + int32_t ret = 0; + ret = duet_flash_kv_del(key); + return ConvertKVResultToChip(ret); +} + +CHIP_ERROR KeyValueStoreManagerImpl::Erase(void) +{ + int32_t ret = 0; + lega_rtos_declare_critical(); + lega_rtos_enter_critical(); + ret = duet_flash_erase(PARTITION_PARAMETER_2, 0, KV_MAX_SIZE); + lega_rtos_exit_critical(); + + return ConvertKVResultToChip(ret); +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/KeyValueStoreManagerImpl.h b/src/platform/ASR/KeyValueStoreManagerImpl.h new file mode 100755 index 00000000000000..80836439c68bc2 --- /dev/null +++ b/src/platform/ASR/KeyValueStoreManagerImpl.h @@ -0,0 +1,73 @@ +/* + * + * 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 + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +class KeyValueStoreManagerImpl final : public KeyValueStoreManager +{ + // Allow the KeyValueStoreManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class KeyValueStoreManager; + +public: + CHIP_ERROR Init(); + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) const; + CHIP_ERROR _Delete(const char * key); + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size); + CHIP_ERROR Erase(void); + +private: + // ===== Members for internal use by the following friends. + friend KeyValueStoreManager & KeyValueStoreMgr(); + friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); + + static KeyValueStoreManagerImpl sInstance; + + CHIP_ERROR ConvertKVResultToChip(int32_t err) const; + + bool init_success = false; +}; + +/** + * Returns the public interface of the KeyValueStoreManager singleton object. + * + * Chip applications should use this to access features of the KeyValueStoreManager object + * that are common to all platforms. + */ +inline KeyValueStoreManager & KeyValueStoreMgr(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager + * that are specific to the ASR platform. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/Logging.cpp b/src/platform/ASR/Logging.cpp new file mode 100644 index 00000000000000..1fc0114fc3bdce --- /dev/null +++ b/src/platform/ASR/Logging.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#if (CFG_EASY_LOG_ENABLE == 1) +#include "elog.h" +#if (CFG_EASY_LOG_MODULE_EN == 1) +#include "elog_module.h" +#endif +#endif + +namespace chip { +namespace DeviceLayer { + +/** + * Called whenever a log message is emitted by Chip or LwIP. + * + * This function is intended be overridden by the application to, e.g., + * schedule output of queued log entries. + */ +void __attribute__((weak)) OnLogOutput(void) {} + +} // namespace DeviceLayer +} // namespace chip + +namespace chip { +namespace Logging { +namespace Platform { + +/** + * CHIP log output functions. + */ +void LogV(const char * module, uint8_t category, const char * msg, va_list v) +{ +#if ASR_LOG_ENABLED && _CHIP_USE_LOGGING +#if ((CFG_EASY_LOG_ENABLE == 1) && (CFG_EASY_LOG_MODULE_EN == 1)) + char log_tag[10]; + snprintf(log_tag, sizeof(log_tag), "CHIP:%s", module); + switch (category) + { + case kLogCategory_Error: + mlog_e(log_tag, msg, v); + break; + case kLogCategory_Progress: + mlog_i(log_tag, msg, v); + break; + case kLogCategory_Detail: + mlog_v(log_tag, msg, v); + break; + case kLogCategory_Automation: + mlog_d(log_tag, msg, v); + break; + case kLogCategory_None: + mlog_w(log_tag, msg, v); + break; + default: + mlog_a(log_tag, msg, v); + break; + } +#else + printf("CHIP:%s: ", module); + vprintf(msg, v); + printf("\n"); +#endif + // Let the application know that a log message has been emitted. + DeviceLayer::OnLogOutput(); +#endif +} + +void LogV2(const char * module, const char * msg, va_list v) +{ +#if ((CFG_EASY_LOG_ENABLE == 1) && (CFG_EASY_LOG_MODULE_EN == 1)) + elog_chip_printf(module, msg, v); +#else + printf("%s: ", module); + vprintf(msg, v); + printf("\n"); +#endif +} + +extern "C" void ASR_LOG(const char * aFormat, ...) +{ + va_list v; + va_start(v, aFormat); + LogV2("ASR:", aFormat, v); + va_end(v); +} + +} // namespace Platform +} // namespace Logging +} // namespace chip diff --git a/src/platform/ASR/LwIPCoreLock.cpp b/src/platform/ASR/LwIPCoreLock.cpp new file mode 100644 index 00000000000000..2518600983d412 --- /dev/null +++ b/src/platform/ASR/LwIPCoreLock.cpp @@ -0,0 +1,62 @@ +/* + * + * Copyright (c) 2021 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. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +namespace { + +lega_mutex_t LwIPCoreLock; + +} + +namespace chip { +namespace DeviceLayer { +namespace Internal { + +CHIP_ERROR InitLwIPCoreLock(void) +{ + if (LwIPCoreLock == NULL) + { + lega_rtos_init_mutex(&LwIPCoreLock); + if (LwIPCoreLock == NULL) + { + ChipLogError(DeviceLayer, "Failed to create LwIP core lock"); + return CHIP_ERROR_NO_MEMORY; + } + } + + return CHIP_NO_ERROR; +} + +} // namespace Internal +} // namespace DeviceLayer +} // namespace chip + +extern "C" void lock_lwip_core() +{ + lega_rtos_lock_mutex(&LwIPCoreLock, LEGA_WAIT_FOREVER); +} + +extern "C" void unlock_lwip_core() +{ + lega_rtos_unlock_mutex(&LwIPCoreLock); +} diff --git a/src/platform/ASR/NetworkCommissioningDriver.h b/src/platform/ASR/NetworkCommissioningDriver.h new file mode 100644 index 00000000000000..954f0c886be2d5 --- /dev/null +++ b/src/platform/ASR/NetworkCommissioningDriver.h @@ -0,0 +1,153 @@ +/* + * + * 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 "lega_wlan_api.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { + +namespace { +constexpr uint8_t kMaxWiFiNetworks = 1; +constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; +constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 20; +constexpr uint8_t kWiFiMaxNetworks = 15; +} // namespace + +class ASRScanResponseIterator : public Iterator +{ +public: + ASRScanResponseIterator(const size_t size, const lega_wlan_scan_result_t * scanResults) : + mSize(size), mpScanResults(scanResults) + {} + size_t Count() override { return mSize; } + bool Next(WiFiScanResponse & item) override + { + if (mIternum >= mSize) + { + return false; + } + + // copy the available information into WiFiScanResponse struct, which will be copied to the result to be sent + item.security.SetRaw(mpScanResults->ap_list[mIternum].security); + item.ssidLen = static_cast(strnlen(reinterpret_cast(mpScanResults->ap_list[mIternum].ssid), + chip::DeviceLayer::Internal::kMaxWiFiSSIDLength)); + item.channel = mpScanResults->ap_list[mIternum].channel; + item.wiFiBand = chip::DeviceLayer::NetworkCommissioning::WiFiBand::k2g4; + item.rssi = mpScanResults->ap_list[mIternum].ap_power; + memcpy(item.ssid, mpScanResults->ap_list[mIternum].ssid, item.ssidLen); + memcpy(item.bssid, mpScanResults->ap_list[mIternum].bssid, 6); + + mIternum++; + return true; + } + void Release() override {} + +private: + const size_t mSize; // no of network scanned + const lega_wlan_scan_result_t * mpScanResults; // list of scanned network info of size mSize + size_t mIternum = 0; // to iterate through mpScanResults of size mSize +}; + +class ASRWiFiDriver final : public WiFiDriver +{ +public: + class WiFiNetworkIterator final : public NetworkIterator + { + public: + WiFiNetworkIterator(ASRWiFiDriver * aDriver) : mDriver(aDriver) {} + size_t Count() override; + bool Next(Network & item) override; + void Release() override { delete this; } + ~WiFiNetworkIterator() = default; + + private: + ASRWiFiDriver * mDriver; + bool mExhausted = false; + }; + + struct WiFiNetwork + { + char ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength]; + uint8_t ssidLen = 0; + char credentials[DeviceLayer::Internal::kMaxWiFiKeyLength]; + uint8_t credentialsLen = 0; + }; + + // BaseDriver + NetworkIterator * GetNetworks() override { return new WiFiNetworkIterator(this); } + CHIP_ERROR Init(NetworkStatusChangeCallback * networkStatusChangeCallback) override; + void Shutdown() override; + + // WirelessDriver + uint8_t GetMaxNetworks() override { return kMaxWiFiNetworks; } + uint8_t GetScanNetworkTimeoutSeconds() override { return kWiFiScanNetworksTimeOutSeconds; } + uint8_t GetConnectNetworkTimeoutSeconds() override { return kWiFiConnectNetworkTimeoutSeconds; } + + CHIP_ERROR CommitConfiguration() override; + CHIP_ERROR RevertConfiguration() override; + + Status RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override; + Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) override; + void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override; + + // WiFiDriver + Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, + uint8_t & outNetworkIndex) override; + void ScanNetworks(ByteSpan ssid, ScanCallback * callback) override; + + CHIP_ERROR ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen); + + void OnConnectWiFiNetwork(); + void OnScanWiFiNetworkDone(lega_wlan_scan_result_t * ScanResult); + void OnNetworkStatusChange(); + + CHIP_ERROR SetLastDisconnectReason(int32_t reason); + int32_t GetLastDisconnectReason(); + + static ASRWiFiDriver & GetInstance() + { + static ASRWiFiDriver instance; + return instance; + } + +private: + bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId); + CHIP_ERROR StartScanWiFiNetworks(ByteSpan ssid); + + WiFiNetwork mSavedNetwork; + WiFiNetwork mStagingNetwork; + ScanCallback * mpScanCallback; + ConnectCallback * mpConnectCallback; + NetworkStatusChangeCallback * mpStatusChangeCallback = nullptr; + int32_t mLastDisconnectedReason; +}; + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/NetworkCommissioningWiFiDriver.cpp b/src/platform/ASR/NetworkCommissioningWiFiDriver.cpp new file mode 100644 index 00000000000000..5c8167569f8e78 --- /dev/null +++ b/src/platform/ASR/NetworkCommissioningWiFiDriver.cpp @@ -0,0 +1,352 @@ +/* + * + * 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 +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::chip; +using namespace ::chip::DeviceLayer::Internal; + +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { + +CHIP_ERROR ASRWiFiDriver::Init(NetworkStatusChangeCallback * networkStatusChangeCallback) +{ + CHIP_ERROR err; + mpScanCallback = nullptr; + mpConnectCallback = nullptr; + mpStatusChangeCallback = networkStatusChangeCallback; + + lega_wlan_wifi_conf config = { 0 }; + err = chip::DeviceLayer::Internal::ASRUtils::asr_wifi_get_config(&config); + + if (err == CHIP_ERROR_KEY_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + + memcpy(mSavedNetwork.ssid, config.wifi_ssid, config.ssid_len + 1); + memcpy(mSavedNetwork.credentials, config.wifi_key, config.key_len + 1); + mSavedNetwork.ssidLen = config.ssid_len; + mSavedNetwork.credentialsLen = config.key_len; + + mStagingNetwork = mSavedNetwork; + + return err; +} + +void ASRWiFiDriver::Shutdown() +{ + mpStatusChangeCallback = nullptr; +} + +CHIP_ERROR ASRWiFiDriver::CommitConfiguration() +{ + lega_wlan_wifi_conf config = { 0 }; + memcpy(config.wifi_ssid, mStagingNetwork.ssid, mStagingNetwork.ssidLen); + memcpy(config.wifi_key, mStagingNetwork.credentials, mStagingNetwork.credentialsLen); + config.ssid_len = mStagingNetwork.ssidLen; + config.key_len = mStagingNetwork.credentialsLen; + + ReturnErrorOnFailure(chip::DeviceLayer::Internal::ASRUtils::asr_wifi_set_config(&config)); + + mSavedNetwork = mStagingNetwork; + return CHIP_NO_ERROR; +} + +CHIP_ERROR ASRWiFiDriver::RevertConfiguration() +{ + mStagingNetwork = mSavedNetwork; + return CHIP_NO_ERROR; +} + +bool ASRWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId) +{ + return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0; +} + +Status ASRWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, + uint8_t & outNetworkIndex) +{ + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded); + VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange); + VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange); + + memset(mStagingNetwork.credentials, 0, sizeof(mStagingNetwork.credentials)); + memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size()); + mStagingNetwork.credentialsLen = static_cast(credentials.size()); + + memset(mStagingNetwork.ssid, 0, sizeof(mStagingNetwork.ssid)); + memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size()); + mStagingNetwork.ssidLen = static_cast(ssid.size()); + + return Status::kSuccess; +} + +Status ASRWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) +{ + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + + // Use empty ssid for representing invalid network + mStagingNetwork.ssidLen = 0; + return Status::kSuccess; +} + +Status ASRWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) +{ + outDebugText.reduce_size(0); + // Only one network is supported now + VerifyOrReturnError(index == 0, Status::kOutOfRange); + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + return Status::kSuccess; +} + +CHIP_ERROR ASRWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); + // Set the wifi configuration + lega_wlan_wifi_conf wifiConfig; + + // Set the wifi configuration + memset(&wifiConfig, 0, sizeof(wifiConfig)); + memcpy(wifiConfig.wifi_ssid, ssid, ssidLen); + memcpy(wifiConfig.wifi_key, key, keyLen); + wifiConfig.ssid_len = ssidLen; + wifiConfig.key_len = keyLen; + + err = chip::DeviceLayer::Internal::ASRUtils::asr_wifi_set_config(&wifiConfig); + SuccessOrExit(err); + + ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); + err = ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled); + +exit: + return err; +} + +void ASRWiFiDriver::OnConnectWiFiNetwork() +{ + if (mpConnectCallback) + { + CommitConfiguration(); + mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0); + mpConnectCallback = nullptr; + } +} + +void ASRWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + Status networkingStatus = Status::kSuccess; + + VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound); + VerifyOrExit(mpConnectCallback == nullptr, networkingStatus = Status::kUnknownError); + ChipLogProgress(NetworkProvisioning, "ASR NetworkCommissioningDelegate: SSID: %s", StringOrNullMarker(mStagingNetwork.ssid)); + err = ConnectWiFiNetwork(reinterpret_cast(mStagingNetwork.ssid), mStagingNetwork.ssidLen, + reinterpret_cast(mStagingNetwork.credentials), mStagingNetwork.credentialsLen); + mpConnectCallback = callback; +exit: + if (err != CHIP_NO_ERROR) + { + networkingStatus = Status::kUnknownError; + } + if (networkingStatus != Status::kSuccess) + { + ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network:%s", chip::ErrorStr(err)); + mpConnectCallback = nullptr; + callback->OnResult(networkingStatus, CharSpan(), 0); + } +} +// asr wifi +#include "lega_wlan_api.h" +CHIP_ERROR ASRWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid) +{ + if (ASRUtils::EnableStationMode() != CHIP_NO_ERROR) + { + ChipLogProgress(DeviceLayer, "Start Scan WiFi Networks Failed"); + return CHIP_ERROR_INTERNAL; + } + + if (!ssid.empty()) // ssid is given, only scan this network + { + char cSsid[DeviceLayer::Internal::kMaxWiFiSSIDLength] = {}; + memcpy(cSsid, ssid.data(), ssid.size()); + lega_wlan_start_scan_active(cSsid, 0); + } + else // scan all networks + { + lega_wlan_start_scan(); + } + return CHIP_NO_ERROR; +} + +void ASRWiFiDriver::OnScanWiFiNetworkDone(lega_wlan_scan_result_t * ScanResult) +{ + uint8_t ap_num = ScanResult->ap_num; + if (!ap_num) + { + ChipLogProgress(DeviceLayer, "No AP found"); + if (mpScanCallback != nullptr) + { + mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), nullptr); + mpScanCallback = nullptr; + } + return; + } + + if (ScanResult) + { + if (CHIP_NO_ERROR == DeviceLayer::SystemLayer().ScheduleLambda([ap_num, ScanResult]() { + ASRScanResponseIterator iter(ap_num, ScanResult); + if (GetInstance().mpScanCallback) + { + GetInstance().mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), &iter); + GetInstance().mpScanCallback = nullptr; + } + else + { + ChipLogError(DeviceLayer, "can't find the ScanCallback function"); + } + })) + { + ChipLogProgress(DeviceLayer, "ScheduleLambda OK"); + } + } + else + { + ChipLogError(DeviceLayer, "can't get ap_records "); + if (mpScanCallback) + { + mpScanCallback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); + mpScanCallback = nullptr; + } + } +} + +void ASRWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback) +{ + if (callback != nullptr) + { + mpScanCallback = callback; + if (StartScanWiFiNetworks(ssid) != CHIP_NO_ERROR) + { + mpScanCallback = nullptr; + callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); + } + } +} + +CHIP_ERROR GetConnectedNetwork(Network & network) +{ + lega_wlan_ap_info_adv_t * apinfo = lega_wlan_get_associated_apinfo(); + + if ((apinfo == NULL) || (apinfo->ssid[0] == 0)) + { + return CHIP_ERROR_INTERNAL; + } + uint8_t length = strnlen(reinterpret_cast(apinfo->ssid), DeviceLayer::Internal::kMaxWiFiSSIDLength); + if (length > sizeof(network.networkID)) + { + ChipLogError(DeviceLayer, "SSID too long"); + return CHIP_ERROR_INTERNAL; + } + memcpy(network.networkID, apinfo->ssid, length); + network.networkIDLen = length; + + return CHIP_NO_ERROR; +} + +void ASRWiFiDriver::OnNetworkStatusChange() +{ + Network configuredNetwork; + bool staEnabled = false, staConnected = false; + VerifyOrReturn(ASRUtils::IsStationEnabled(staEnabled) == CHIP_NO_ERROR); + VerifyOrReturn(staEnabled && mpStatusChangeCallback != nullptr); + CHIP_ERROR err = GetConnectedNetwork(configuredNetwork); + if (err != CHIP_NO_ERROR) + { + return; + } + VerifyOrReturn(ASRUtils::IsStationConnected(staConnected) == CHIP_NO_ERROR); + if (staConnected) + { + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kSuccess, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), + MakeOptional(GetLastDisconnectReason())); + return; + } + mpStatusChangeCallback->OnNetworkingStatusChange( + Status::kUnknownError, MakeOptional(ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)), + MakeOptional(GetLastDisconnectReason())); +} + +CHIP_ERROR ASRWiFiDriver::SetLastDisconnectReason(int32_t reason) +{ + mLastDisconnectedReason = reason; + return CHIP_NO_ERROR; +} + +int32_t ASRWiFiDriver::GetLastDisconnectReason() +{ + return mLastDisconnectedReason; +} + +size_t ASRWiFiDriver::WiFiNetworkIterator::Count() +{ + return mDriver->mStagingNetwork.ssidLen == 0 ? 0 : 1; +} + +bool ASRWiFiDriver::WiFiNetworkIterator::Next(Network & item) +{ + if (mExhausted || mDriver->mStagingNetwork.ssidLen == 0) + { + return false; + } + memcpy(item.networkID, mDriver->mStagingNetwork.ssid, mDriver->mStagingNetwork.ssidLen); + item.networkIDLen = mDriver->mStagingNetwork.ssidLen; + item.connected = false; + mExhausted = true; + + Network connectedNetwork; + CHIP_ERROR err = GetConnectedNetwork(connectedNetwork); + if (err == CHIP_NO_ERROR) + { + if (connectedNetwork.networkIDLen == item.networkIDLen && + memcmp(connectedNetwork.networkID, item.networkID, item.networkIDLen) == 0) + { + item.connected = true; + } + } + return true; +} + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/PlatformManagerImpl.cpp b/src/platform/ASR/PlatformManagerImpl.cpp new file mode 100644 index 00000000000000..31172ae5f94a17 --- /dev/null +++ b/src/platform/ASR/PlatformManagerImpl.cpp @@ -0,0 +1,353 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the PlatformManager object. + */ +/* this file behaves like a config.h, comes first */ +#include + +#include +#include +#if CONFIG_ENABLE_ASR_LEGA_RTOS +#include +#else +#include +#endif +#include + +namespace chip { +namespace DeviceLayer { + +namespace Internal { +extern CHIP_ERROR InitLwIPCoreLock(void); +} + +PlatformManagerImpl PlatformManagerImpl::sInstance; + +CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) +{ +#if CONFIG_ENABLE_ASR_LEGA_RTOS + CHIP_ERROR err = CHIP_NO_ERROR; + OSStatus result; + + /* Initialize LwIP lock. */ + err = Internal::InitLwIPCoreLock(); + SuccessOrExit(err); + + /* Initialize the event flags. */ + result = lega_rtos_init_event_flags(&mEventFlags); + VerifyOrExit(result == kNoErr, err = CHIP_ERROR_NO_MEMORY); + + /* Initialize the event queue. */ + result = lega_rtos_init_queue(&mEventQueue, "EventQueue", sizeof(ChipDeviceEvent), CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE); + VerifyOrExit(result == kNoErr, err = CHIP_ERROR_NO_MEMORY); + + /* Initialize the timer. */ + result = lega_rtos_init_timer(&mTimer, 1000, (timer_handler_t) TimerCallback, (void *) this); + VerifyOrExit(result == kNoErr, err = CHIP_ERROR_INTERNAL); + + /* Initialize the mutex. */ + result = lega_rtos_init_mutex(&mChipMutex); + VerifyOrExit(result == kNoErr, err = CHIP_ERROR_INTERNAL); + + result = lega_rtos_init_mutex(&mEventMutex); + VerifyOrExit(result == kNoErr, err = CHIP_ERROR_INTERNAL); + + ReturnErrorOnFailure(GenericPlatformManagerImpl::_InitChipStack()); +#else + CHIP_ERROR err; + + // Make sure the LwIP core lock has been initialized + err = Internal::InitLwIPCoreLock(); + SuccessOrExit(err); + + mStartTime = System::SystemClock().GetMonotonicTimestamp(); + + // Call _InitChipStack() on the generic implementation base class + // to finish the initialization process. + err = Internal::GenericPlatformManagerImpl_FreeRTOS::_InitChipStack(); + SuccessOrExit(err); +#endif +exit: + return err; +} + +#if CONFIG_ENABLE_ASR_LEGA_RTOS + +void PlatformManagerImpl::_RunEventLoop() +{ + kTaskRunningEventFlag = 1; + + RunEventLoopInternal(); +} + +void PlatformManagerImpl::RunEventLoopInternal(void) +{ + while (true) + { + uint32_t flags_set = 0; + + OSStatus result = lega_rtos_wait_for_event_flags(&mEventFlags, kPostEventFlag | kTimerEventFlag | kTaskStopEventFlag, + &flags_set, TRUE, WAIT_FOR_ANY_EVENT, LEGA_WAIT_FOREVER); + + if (result != kNoErr) + { + ChipLogError(DeviceLayer, "lega_rtos_wait_for_event_flags 0x%08x", result); + continue; + } + + if (flags_set & kTaskStopEventFlag) + { + kTaskRunningEventFlag = 0; + break; + } + + if (flags_set & kTimerEventFlag) + { + HandleTimerEvent(); + } + + if (flags_set & kPostEventFlag) + { + HandlePostEvent(); + } + + if (kTaskRunningEventFlag == 0) + { + break; + } + } +} + +CHIP_ERROR PlatformManagerImpl::_StartEventLoopTask(void) +{ + lega_task_config_t cfg; + + lega_rtos_lock_mutex(&mEventMutex, LEGA_WAIT_FOREVER); + + if (kTaskRunningEventFlag == 1) + { + lega_rtos_unlock_mutex(&mEventMutex); + return CHIP_ERROR_BUSY; + } + + MatterInitializer::Matter_Task_Config(&cfg); + + kTaskRunningEventFlag = 1; + + OSStatus result = lega_rtos_create_thread(&mThread, cfg.task_priority, CHIP_DEVICE_CONFIG_CHIP_TASK_NAME, + (lega_thread_function_t) EventLoopTaskMain, cfg.stack_size, (lega_thread_arg_t) this); + + if (result != kNoErr) + { + lega_rtos_unlock_mutex(&mEventMutex); + return CHIP_ERROR_INTERNAL; + } + + lega_rtos_unlock_mutex(&mEventMutex); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PlatformManagerImpl::_StopEventLoopTask() +{ + lega_rtos_lock_mutex(&mEventMutex, LEGA_WAIT_FOREVER); + + if (kTaskRunningEventFlag == 0) + { + lega_rtos_unlock_mutex(&mEventMutex); + return CHIP_ERROR_INCORRECT_STATE; + } + + PlatformMgrImpl().SetEventFlags(kTaskStopEventFlag); + + lega_rtos_unlock_mutex(&mEventMutex); + + return CHIP_NO_ERROR; +} + +void PlatformManagerImpl::_LockChipStack(void) +{ + OSStatus result = lega_rtos_lock_mutex(&mChipMutex, LEGA_WAIT_FOREVER); + VerifyOrReturn(result == kNoErr, ChipLogError(DeviceLayer, "%s %x", __func__, result)); +} + +void PlatformManagerImpl::_UnlockChipStack(void) +{ + OSStatus result = lega_rtos_unlock_mutex(&mChipMutex); + VerifyOrReturn(result == kNoErr, ChipLogError(DeviceLayer, "%s %x", __func__, result)); +} + +CHIP_ERROR PlatformManagerImpl::_PostEvent(const ChipDeviceEvent * event) +{ + OSStatus result = lega_rtos_push_to_queue(&mEventQueue, const_cast(event), LEGA_NO_WAIT); + if (kNoErr != result) + { + ChipLogError(DeviceLayer, "lega_rtos_push_to_queue %u", result); + return CHIP_ERROR_INTERNAL; + } + + PlatformMgrImpl().SetEventFlags(kPostEventFlag); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PlatformManagerImpl::_StartChipTimer(System::Clock::Timeout durationMS) +{ + if (durationMS.count() == 0) + { + TimerCallback(0); + } + else + { + lega_rtos_deinit_timer(&mTimer); + lega_rtos_init_timer(&mTimer, durationMS.count(), (timer_handler_t) TimerCallback, (void *) this); + OSStatus result = lega_rtos_start_timer(&mTimer); + if (kNoErr != result) + { + ChipLogError(DeviceLayer, "wiced_start_timer 0x%02x", result); + return CHIP_ERROR_INTERNAL; + } + } + return CHIP_NO_ERROR; +} +#else +CHIP_ERROR PlatformManagerImpl::InitLwIPCoreLock(void) +{ + return Internal::InitLwIPCoreLock(); +} +#endif + +void PlatformManagerImpl::_Shutdown() +{ + uint64_t upTime = 0; + + if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR) + { + uint32_t totalOperationalHours = 0; + + if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR) + { + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast(upTime / 3600)); + } + else + { + ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node"); + } + } + else + { + ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot"); + } +#if CONFIG_ENABLE_ASR_LEGA_RTOS + // + // Call up to the base class _Shutdown() to perform the actual stack de-initialization + // and clean-up + // + + (void) _StopEventLoopTask(); + + // the task thread is self terminating, we might have to wait if it's still processing + while (true) + { + if (kTaskRunningEventFlag == 0) + { + break; + } + lega_rtos_delay_milliseconds(1); + } + + ChipLogError(DeviceLayer, "StopEventLoopTask done."); + + lega_rtos_deinit_event_flags(&mEventFlags); + lega_rtos_deinit_queue(&mEventQueue); + lega_rtos_deinit_timer(&mTimer); + lega_rtos_deinit_mutex(&mChipMutex); + lega_rtos_deinit_mutex(&mEventMutex); + + Internal::GenericPlatformManagerImpl::_Shutdown(); +#else + Internal::GenericPlatformManagerImpl_FreeRTOS::_Shutdown(); +#endif +} + +#if CONFIG_ENABLE_ASR_LEGA_RTOS +void PlatformManagerImpl::SetEventFlags(uint32_t flags) +{ + if (lega_rtos_set_event_flags(&mEventFlags, flags) != kNoErr) + { + ChipLogError(DeviceLayer, "%s lega_rtos_set_event_flags %08lx", __func__, flags); + } +} + +void PlatformManagerImpl::HandleTimerEvent(void) +{ + const CHIP_ERROR err = static_cast(DeviceLayer::SystemLayer()).HandlePlatformTimer(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "HandlePlatformTimer %ld", err.AsInteger()); + } +} + +void PlatformManagerImpl::HandlePostEvent(void) +{ + OSStatus result; + ChipDeviceEvent event; + + /* Check the event queue. */ + if (lega_rtos_is_queue_empty(&mEventQueue)) + { + return; + } + + /* Pop one event from the event queue. */ + result = lega_rtos_pop_from_queue(&mEventQueue, &event, LEGA_WAIT_FOREVER); + + if (kNoErr != result) + { + ChipLogError(DeviceLayer, "lega_rtos_pop_from_queue %u", result); + return; + } + + /* Process this event. */ + DispatchEvent(&event); + + /* Set another application thread event if the event queue is not empty. */ + if (!lega_rtos_is_queue_empty(&mEventQueue)) + { + PlatformMgrImpl().SetEventFlags(kPostEventFlag); + } +} + +void PlatformManagerImpl::EventLoopTaskMain(uint32_t arg) +{ + ChipLogDetail(DeviceLayer, "CHIP task running"); + PlatformMgrImpl().RunEventLoopInternal(); + lega_rtos_delete_thread(NULL); +} + +void PlatformManagerImpl::TimerCallback(void * params) +{ + PlatformMgrImpl().SetEventFlags(kTimerEventFlag); +} +#endif + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/PlatformManagerImpl.h b/src/platform/ASR/PlatformManagerImpl.h new file mode 100644 index 00000000000000..c3d5388a23c129 --- /dev/null +++ b/src/platform/ASR/PlatformManagerImpl.h @@ -0,0 +1,129 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Provides an implementation of the PlatformManager object. + * for the ASR platform. + */ + +#pragma once +#if CONFIG_ENABLE_ASR_LEGA_RTOS +#include +#else +#include +#endif +namespace chip { +namespace DeviceLayer { + +/** + * Concrete implementation of the PlatformManager singleton object for the ASR platform. + */ +#if CONFIG_ENABLE_ASR_LEGA_RTOS +class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl +#else +class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_FreeRTOS +#endif +{ + // Allow the PlatformManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend PlatformManager; +#if CONFIG_ENABLE_ASR_LEGA_RTOS +public: + inline bool IsCurrentTask(void) { return lega_rtos_is_current_thread(&mThread) == TRUE; } +#else + // Allow the generic implementation base class to call helper methods on + // this class. +#ifndef DOXYGEN_SHOULD_SKIP_THIS + friend Internal::GenericPlatformManagerImpl_FreeRTOS; +#endif + +public: + // ===== Platform-specific members that may be accessed directly by the application. + + CHIP_ERROR InitLwIPCoreLock(void); +#endif + System::Clock::Timestamp GetStartTime() { return mStartTime; } + +private: + // ===== Methods that implement the PlatformManager abstract interface. + + CHIP_ERROR _InitChipStack(void); + void _Shutdown(); + + // ===== Members for internal use by the following friends. + + friend PlatformManager & PlatformMgr(void); + friend PlatformManagerImpl & PlatformMgrImpl(void); + + System::Clock::Timestamp mStartTime = System::Clock::kZero; + + static PlatformManagerImpl sInstance; +#if CONFIG_ENABLE_ASR_LEGA_RTOS + void _RunEventLoop(void); + CHIP_ERROR _StartEventLoopTask(void); + CHIP_ERROR _StopEventLoopTask(void); + void _LockChipStack(void); + bool _TryLockChipStack(void); + void _UnlockChipStack(void); + CHIP_ERROR _PostEvent(const ChipDeviceEvent * event); + CHIP_ERROR _StartChipTimer(System::Clock::Timeout durationMS); + void SetEventFlags(uint32_t flags); + void HandleTimerEvent(void); + void HandlePostEvent(void); + + lega_thread_t mThread; + lega_event_flags_t mEventFlags; + lega_queue_t mEventQueue; + lega_timer_t mTimer; + lega_mutex_t mChipMutex; + lega_mutex_t mEventMutex; + static void EventLoopTaskMain(uint32_t arg); + void RunEventLoopInternal(void); + static void TimerCallback(void * params); + uint32_t kTaskRunningEventFlag; + static constexpr uint32_t kTaskStopEventFlag = 1 << 0; + static constexpr uint32_t kPostEventFlag = 1 << 1; + static constexpr uint32_t kTimerEventFlag = 1 << 2; +#endif +}; + +/** + * Returns the public interface of the PlatformManager singleton object. + * + * Chip applications should use this to access features of the PlatformManager object + * that are common to all platforms. + */ +inline PlatformManager & PlatformMgr(void) +{ + return PlatformManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the PlatformManager singleton object. + * + * Chip applications can use this to gain access to features of the PlatformManager + * that are specific to the ASR platform. + */ +inline PlatformManagerImpl & PlatformMgrImpl(void) +{ + return PlatformManagerImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/ASR/SystemPlatformConfig.h b/src/platform/ASR/SystemPlatformConfig.h new file mode 100755 index 00000000000000..a4714a7cadc183 --- /dev/null +++ b/src/platform/ASR/SystemPlatformConfig.h @@ -0,0 +1,42 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * + * 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 + +namespace chip { +namespace DeviceLayer { +struct ChipDeviceEvent; +} // namespace DeviceLayer +} // namespace chip + +// ==================== Platform Adaptations ==================== + +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_EVENT_FUNCTIONS 1 +#define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 0 +#define CHIP_SYSTEM_CONFIG_LWIP_EVENT_TYPE int +#define CHIP_SYSTEM_CONFIG_LWIP_EVENT_OBJECT_TYPE const struct ::chip::DeviceLayer::ChipDeviceEvent * +#define CHIP_SYSTEM_CONFIG_EVENT_OBJECT_TYPE const struct ::chip::DeviceLayer::ChipDeviceEvent * +#define CHIP_SYSTEM_CONFIG_ERROR_TYPE uint32_t +#define CHIP_SYSTEM_CONFIG_NO_ERROR 0 +#define CHIP_SYSTEM_CONFIG_ERROR_MIN 7000000 +#define CHIP_SYSTEM_CONFIG_ERROR_MAX 7000999 +#define _CHIP_SYSTEM_CONFIG_ERROR(e) (CHIP_SYSTEM_CONFIG_ERROR_MIN + (e)) +#define CHIP_SYSTEM_LWIP_ERROR_MIN 3000000 +#define CHIP_SYSTEM_LWIP_ERROR_MAX 3000128 diff --git a/src/platform/ASR/SystemTimeSupport.cpp b/src/platform/ASR/SystemTimeSupport.cpp new file mode 100644 index 00000000000000..8b729a86dd50a3 --- /dev/null +++ b/src/platform/ASR/SystemTimeSupport.cpp @@ -0,0 +1,88 @@ +/* + * + * 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. + */ + +/* this file behaves like a config.h, comes first */ +#include + +#include +#include + +#include + +#if CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME + +namespace chip { +namespace System { +namespace Clock { + +namespace Internal { +ClockImpl gClockImpl; +} // namespace Internal + +Microseconds64 ClockImpl::GetMonotonicMicroseconds64(void) +{ + return Clock::Microseconds64(lega_rtos_get_time() * 1000l); +} + +Milliseconds64 ClockImpl::GetMonotonicMilliseconds64(void) +{ + return std::chrono::duration_cast(GetMonotonicMicroseconds64()); +} + +CHIP_ERROR ClockImpl::GetClock_RealTime(Microseconds64 & aCurTime) +{ + // TODO(19081): This platform does not properly error out if wall clock has + // not been set. For now, short circuit this. + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR ClockImpl::GetClock_RealTimeMS(Milliseconds64 & aCurTime) +{ + Microseconds64 curTimeUs; + auto err = GetClock_RealTime(curTimeUs); + aCurTime = std::chrono::duration_cast(curTimeUs); + return err; +} + +CHIP_ERROR ClockImpl::SetClock_RealTime(Microseconds64 aNewCurTime) +{ + struct timeval tv; + tv.tv_sec = static_cast(aNewCurTime.count() / UINT64_C(1000000)); + tv.tv_usec = static_cast(aNewCurTime.count() % UINT64_C(1000000)); + + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +CHIP_ERROR InitClock_RealTime() +{ + Clock::Microseconds64 curTime = + Clock::Microseconds64((static_cast(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) * UINT64_C(1000000))); + // Use CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD as the initial value of RealTime. + // Then the RealTime obtained from GetClock_RealTime will be always valid. + // + // TODO(19081): This is broken because it causes the platform to report + // that it does have wall clock time when it actually doesn't. + return System::SystemClock().SetClock_RealTime(curTime); +} + +} // namespace Clock +} // namespace System +} // namespace chip + +#endif diff --git a/src/platform/ASR/SystemTimeSupport.h b/src/platform/ASR/SystemTimeSupport.h new file mode 100755 index 00000000000000..da38a26ced25c2 --- /dev/null +++ b/src/platform/ASR/SystemTimeSupport.h @@ -0,0 +1,28 @@ +/* + * + * 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 + +namespace chip { +namespace System { +namespace Clock { + +CHIP_ERROR InitClock_RealTime(); + +} // namespace Clock +} // namespace System +} // namespace chip diff --git a/src/platform/ASR/WarmPlatformConfig.h b/src/platform/ASR/WarmPlatformConfig.h new file mode 100755 index 00000000000000..11598410e73933 --- /dev/null +++ b/src/platform/ASR/WarmPlatformConfig.h @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 2021 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 + +// ==================== Platform Adaptations ==================== + +#define WARM_CONFIG_SUPPORT_THREAD 0 +#define WARM_CONFIG_SUPPORT_THREAD_ROUTING 0 +#define WARM_CONFIG_SUPPORT_LEGACY6LOWPAN_NETWORK 0 +#define WARM_CONFIG_SUPPORT_WIFI 1 +#define WARM_CONFIG_SUPPORT_CELLULAR 0 + +// ========== Platform-specific Configuration Overrides ========= + +/* none so far */ diff --git a/src/platform/ASR/args.gni b/src/platform/ASR/args.gni new file mode 100755 index 00000000000000..85217656032436 --- /dev/null +++ b/src/platform/ASR/args.gni @@ -0,0 +1,27 @@ +# Copyright (c) 2023 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") + +riscv_platform_config = "${chip_root}/third_party/asr/asr_riscv.gni" + +chip_device_platform = "asr" + +lwip_platform = "asr" + +chip_build_tests = false + +chip_inet_config_enable_ipv4 = true +chip_inet_config_enable_tcp_endpoint = true +chip_inet_config_enable_udp_endpoint = true diff --git a/src/platform/ASR/route_hook/asr_route_hook.c b/src/platform/ASR/route_hook/asr_route_hook.c new file mode 100644 index 00000000000000..0dae344f057e99 --- /dev/null +++ b/src/platform/ASR/route_hook/asr_route_hook.c @@ -0,0 +1,209 @@ +#include +#include + +#include "asr_route_hook.h" +#include "asr_route_table.h" + +#include "lwip/icmp6.h" +#include "lwip/mld6.h" +#include "lwip/netif.h" +#include "lwip/prot/icmp6.h" +#include "lwip/prot/ip6.h" +#include "lwip/prot/nd6.h" +#include "lwip/raw.h" + +void ASR_LOG(const char * aFormat, ...); + +typedef struct asr_route_hook_t +{ + struct netif * netif; + struct raw_pcb * pcb; + struct asr_route_hook_t * next; +} asr_route_hook_t; + +PACK_STRUCT_BEGIN +struct rio_header_t +{ + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END + +typedef struct rio_header_t rio_header_t; + +static asr_route_hook_t * s_hooks; + +static bool is_self_address(struct netif * netif, const ip6_addr_t * addr) +{ + for (size_t i = 0; i < LWIP_ARRAYSIZE(netif->ip6_addr); i++) + { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + memcmp(addr->addr, netif_ip6_addr(netif, i)->addr, sizeof(addr->addr)) == 0) + { + return true; + } + } + return false; +} + +static void ra_recv_handler(struct netif * netif, const uint8_t * icmp_payload, uint16_t payload_len, const ip6_addr_t * src_addr) +{ + if (payload_len < sizeof(struct ra_header)) + { + return; + } + icmp_payload += sizeof(struct ra_header); + payload_len -= sizeof(struct ra_header); + + while (payload_len >= 2) + { + uint8_t opt_type = icmp_payload[0]; + uint8_t opt_len = icmp_payload[1] << 3; + + if (opt_type == ND6_OPTION_TYPE_ROUTE_INFO && opt_len >= sizeof(rio_header_t) && !is_self_address(netif, src_addr) && + payload_len >= opt_len) + { + rio_header_t rio_header; + memcpy(&rio_header, icmp_payload, sizeof(rio_header)); + + // skip if prefix is longer than IPv6 address. + if (rio_header.prefix_length > 128) + { + break; + } + uint8_t prefix_len_bytes = (rio_header.prefix_length + 7) / 8; + int8_t preference = -2 * ((rio_header.preference >> 4) & 1) + (((rio_header.preference) >> 3) & 1); + const uint8_t * rio_data = &icmp_payload[sizeof(rio_header_t)]; + uint8_t rio_data_len = opt_len - sizeof(rio_header_t); + + ASR_LOG("Received RIO"); + if (rio_data_len >= prefix_len_bytes) + { + ip6_addr_t prefix; + asr_route_entry_t route; + + memset(&prefix, 0, sizeof(prefix)); + memcpy(&prefix.addr, rio_data, prefix_len_bytes); + route.netif = netif; + route.gateway = *src_addr; + route.prefix_length = rio_header.prefix_length; + route.prefix = prefix; + route.preference = preference; + route.lifetime_seconds = lwip_ntohl(rio_header.route_lifetime); + ASR_LOG("prefix %s lifetime %u", ip6addr_ntoa(&prefix), route.lifetime_seconds); + if (asr_route_table_add_route_entry(&route) == NULL) + { + ASR_LOG("Failed to add route table entry"); + } + else + { + ASR_LOG("Added entry to route table"); + } + } + } + icmp_payload += opt_len; + payload_len -= opt_len; + } +} + +static uint8_t icmp6_raw_recv_handler(void * arg, struct raw_pcb * pcb, struct pbuf * p, const ip_addr_t * addr) +{ + uint8_t * icmp_payload = NULL; + uint16_t icmp_payload_len; + struct ip6_hdr * ip6_header = (struct ip6_hdr *) p->payload; + struct icmp6_hdr * icmp6_header; + ip6_addr_t src; + ip6_addr_t dest; + asr_route_hook_t * hook = (asr_route_hook_t *) arg; + + memcpy(src.addr, ip6_header->src.addr, sizeof(src.addr)); + memcpy(dest.addr, ip6_header->dest.addr, sizeof(dest.addr)); +#if LWIP_IPV6_SCOPES + src.zone = 0; +#endif + + if (p->tot_len != p->len) + { + ASR_LOG("Ignore segmented ICMP packet"); + return 0; + } + if (p->tot_len <= sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) + { + ASR_LOG("Ignore invalid ICMP packet"); + return 0; + } + if (!ip6_addr_islinklocal(&dest) && !ip6_addr_isallnodes_linklocal(&dest) && !ip6_addr_isallrouters_linklocal(&dest)) + { + return 0; + } + + icmp_payload_len = p->tot_len - sizeof(struct ip6_hdr); + icmp_payload = p->payload + sizeof(struct ip6_hdr); + + icmp6_header = (struct icmp6_hdr *) icmp_payload; + if (icmp6_header->type == ICMP6_TYPE_RA) + { + ra_recv_handler(hook->netif, icmp_payload, icmp_payload_len, &src); + } + return 0; +} + +extern struct netif * lwip_get_netif(void); + +int8_t asr_route_hook_init() +{ + struct netif * lwip_netif = lwip_get_netif(); + ip_addr_t router_group = IPADDR6_INIT_HOST(0xFF020000, 0, 0, 0x02); + asr_route_hook_t * hook = NULL; + uint8_t ret = 0; + + if (lwip_netif == NULL) + { + ASR_LOG("Invalid network interface"); + return -1; + } + + for (asr_route_hook_t * iter = s_hooks; iter != NULL; iter++) + { + if (iter->netif == lwip_netif) + { + ASR_LOG("Hook already installed on netif, skip..."); + return 0; + } + } + + hook = (asr_route_hook_t *) malloc(sizeof(asr_route_hook_t)); + if (hook == NULL) + { + ASR_LOG("Cannot allocate hook"); + return -1; + } + + if (mld6_joingroup_netif(lwip_netif, ip_2_ip6(&router_group)) != ERR_OK) + { + ASR_LOG("Failed to join multicast group"); + ret = -1; + goto exit; + } + + hook->netif = lwip_netif; + hook->pcb = raw_new_ip_type(IPADDR_TYPE_V6, IP6_NEXTH_ICMP6); + hook->pcb->flags |= RAW_FLAGS_MULTICAST_LOOP; + hook->pcb->chksum_reqd = 1; + // The ICMPv6 header checksum offset + hook->pcb->chksum_offset = 2; + raw_bind_netif(hook->pcb, lwip_netif); + raw_recv(hook->pcb, icmp6_raw_recv_handler, hook); + hook->next = s_hooks; + s_hooks = hook; + +exit: + if (ret != 0 && hook != NULL) + { + free(hook); + } + return ret; +} diff --git a/src/platform/ASR/route_hook/asr_route_hook.h b/src/platform/ASR/route_hook/asr_route_hook.h new file mode 100755 index 00000000000000..654f4515a2a4ff --- /dev/null +++ b/src/platform/ASR/route_hook/asr_route_hook.h @@ -0,0 +1,10 @@ +#include +#ifdef __cplusplus +extern "C" { +#endif + +int8_t asr_route_hook_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/platform/ASR/route_hook/asr_route_table.c b/src/platform/ASR/route_hook/asr_route_table.c new file mode 100755 index 00000000000000..5c9a0248f5c39a --- /dev/null +++ b/src/platform/ASR/route_hook/asr_route_table.c @@ -0,0 +1,174 @@ +#include "asr_route_table.h" +#include +#include + +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/timeouts.h" + +#define MAX_RIO_ROUTE 20 +#define MAX_RIO_TIMEOUT UINT32_MAX / (1000 * 4) // lwIP defined reasonable timeout value + +static asr_route_entry_t s_route_entries[MAX_RIO_ROUTE]; + +static asr_route_entry_t * find_route_entry(const asr_route_entry_t * route_entry) +{ + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + break; + } + if (s_route_entries[i].netif == route_entry->netif && s_route_entries[i].prefix_length == route_entry->prefix_length && + memcmp(s_route_entries[i].gateway.addr, route_entry->gateway.addr, sizeof(route_entry->gateway.addr)) == 0 && + memcmp(s_route_entries[i].prefix.addr, route_entry->prefix.addr, route_entry->prefix_length / 8) == 0) + { + return &s_route_entries[i]; + } + } + return NULL; +} + +static asr_route_entry_t * find_empty_route_entry(void) +{ + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + return &s_route_entries[i]; + } + } + return NULL; +} + +static void route_timeout_handler(void * arg) +{ + asr_route_entry_t * route = (asr_route_entry_t *) arg; + + asr_route_table_remove_route_entry(route); +} + +asr_route_entry_t * asr_route_table_add_route_entry(const asr_route_entry_t * route_entry) +{ + if (route_entry == NULL || (route_entry->lifetime_seconds > MAX_RIO_TIMEOUT && route_entry->lifetime_seconds != UINT32_MAX)) + { + return NULL; + } + + asr_route_entry_t * entry = find_route_entry(route_entry); + + if (entry == NULL) + { + entry = find_empty_route_entry(); + if (entry == NULL) + { + return NULL; + } + entry->netif = route_entry->netif; + entry->gateway = route_entry->gateway; + ip6_addr_assign_zone(&entry->gateway, IP6_UNICAST, entry->netif); + entry->prefix = route_entry->prefix; + entry->prefix_length = route_entry->prefix_length; + } + else + { + sys_untimeout(route_timeout_handler, entry); + } + entry->preference = route_entry->preference; + entry->lifetime_seconds = route_entry->lifetime_seconds; + if (entry->lifetime_seconds != UINT32_MAX) + { + sys_timeout(entry->lifetime_seconds * 1000, route_timeout_handler, entry); + } + return entry; +} + +int8_t asr_route_table_remove_route_entry(asr_route_entry_t * route_entry) +{ + if (route_entry < &s_route_entries[0] || route_entry > &s_route_entries[LWIP_ARRAYSIZE(s_route_entries)]) + { + return -1; + } + route_entry->netif = NULL; + for (asr_route_entry_t * moved = route_entry; moved < &s_route_entries[LWIP_ARRAYSIZE(s_route_entries) - 1]; moved++) + { + *moved = *(moved + 1); + if (moved->netif == NULL) + { + break; + } + } + return 0; +} + +static inline bool is_better_route(const asr_route_entry_t * lhs, const asr_route_entry_t * rhs) +{ + if (rhs == NULL) + { + return true; + } + if (lhs == NULL) + { + return false; + } + return (lhs->prefix_length > rhs->prefix_length) || + (lhs->prefix_length == rhs->prefix_length && lhs->preference > rhs->preference); +} + +static inline bool route_match(const asr_route_entry_t * route, const ip6_addr_t * dest) +{ + return memcmp(dest, route->prefix.addr, route->prefix_length / 8) == 0; +} + +struct netif * lwip_hook_ip6_route(const ip6_addr_t * src, const ip6_addr_t * dest) +{ + asr_route_entry_t * route = NULL; + + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + break; + } + if (route_match(&s_route_entries[i], dest) && is_better_route(&s_route_entries[i], route)) + { + route = &s_route_entries[i]; + } + } + + if (route) + { + return route->netif; + } + else + { + return NULL; + } +} + +const ip6_addr_t * lwip_hook_nd6_get_gw(struct netif * netif, const ip6_addr_t * dest) +{ + asr_route_entry_t * route = NULL; + + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + break; + } + if (s_route_entries[i].netif == netif && route_match(&s_route_entries[i], dest) && + is_better_route(&s_route_entries[i], route)) + { + route = &s_route_entries[i]; + } + } + + if (route) + { + return &route->gateway; + } + else + { + return NULL; + } +} diff --git a/src/platform/ASR/route_hook/asr_route_table.h b/src/platform/ASR/route_hook/asr_route_table.h new file mode 100755 index 00000000000000..f22a2aa7989c5d --- /dev/null +++ b/src/platform/ASR/route_hook/asr_route_table.h @@ -0,0 +1,76 @@ +#include + +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Route table entry + * + */ +typedef struct +{ + ip6_addr_t prefix; + uint8_t prefix_length; + ip6_addr_t gateway; + int8_t preference; + uint32_t lifetime_seconds; + struct netif * netif; +} asr_route_entry_t; + +/** + * @brief Adds an entry to the route table + * + * @param[in] route_entry The route entry to be added + * + * @return + * - The pointer to the added route entry on success + * - NULL on failure + * + */ +asr_route_entry_t * asr_route_table_add_route_entry(const asr_route_entry_t * route_entry); + +/** + * @brief Removes an entry from the route table + * + * @param[in] route_entry The route entry to be removed + * + * @return + * - 0 + * - -1 The provided route_entry is not in the route table. + * + */ +int8_t asr_route_table_remove_route_entry(asr_route_entry_t * route_entry); + +/** + * @brief The lwIP ip6 route hook, called by the lwIP function ip6_route when sending packets. + * + * @param[in] src The source address + * @param[in] dest The destination address + * + * @return + * - The target interface when route found + * - NULL when route not found + * + */ +struct netif * lwip_hook_ip6_route(const ip6_addr_t * src, const ip6_addr_t * dest); + +/** + * @brief The lwIP gateway hook, called by the lwIP when deciding next hop. + * + * @param[in] netif The output network interface + * @param[in] dest The destination address + * + * @return + * - The gateway address when route found + * - NULL when route not found + * + */ +const ip6_addr_t * lwip_hook_nd6_get_gw(struct netif * netif, const ip6_addr_t * dest); + +#ifdef __cplusplus +} +#endif diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 8cd18955cc43d9..6473ed404beaf9 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -294,6 +294,11 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "CHIP_DEVICE_LAYER_TARGET_OPEN_IOT_SDK=1", "CHIP_DEVICE_LAYER_TARGET=openiotsdk", ] + } else if (chip_device_platform == "asr") { + defines += [ + "CHIP_DEVICE_LAYER_TARGET_ASR=1", + "CHIP_DEVICE_LAYER_TARGET=ASR", + ] } if (chip_device_config_device_software_version_string != "") { @@ -476,6 +481,8 @@ if (chip_device_platform != "none") { _platform_target = "mt793x" } else if (chip_device_platform == "openiotsdk") { _platform_target = "openiotsdk" + } else if (chip_device_platform == "asr") { + _platform_target = "ASR" } else { assert(false, "Unknown chip_device_platform: ${chip_device_platform}") } diff --git a/src/platform/device.gni b/src/platform/device.gni old mode 100755 new mode 100644 index 8b6d9787f2a051..6eb09ace0d32ec --- a/src/platform/device.gni +++ b/src/platform/device.gni @@ -66,6 +66,7 @@ declare_args() { chip_device_platform == "webos" || chip_device_platform == "cc32xx" || chip_device_platform == "bl602" || chip_device_platform == "mw320" || chip_device_platform == "beken" || chip_device_platform == "mt793x" || + chip_device_platform == "asr" || (chip_device_platform == "darwin" && current_os == "mac") # Enable ble support. @@ -87,7 +88,7 @@ declare_args() { chip_device_platform == "ameba" || chip_device_platform == "webos" || chip_device_platform == "cc32xx" || chip_device_platform == "bl602" || chip_device_platform == "mw320" || chip_device_platform == "beken" || - chip_device_platform == "mt793x" || + chip_device_platform == "mt793x" || chip_device_platform == "asr" || chip_device_platform == "openiotsdk") { chip_mdns = "minimal" } else if (chip_device_platform == "darwin" || @@ -168,6 +169,8 @@ if (chip_device_platform == "cc13x2_26x2") { _chip_device_layer = "mt793x" } else if (chip_device_platform == "openiotsdk") { _chip_device_layer = "openiotsdk" +} else if (chip_device_platform == "asr") { + _chip_device_layer = "ASR" } if (chip_device_platform != "external") { @@ -236,5 +239,5 @@ assert( chip_device_platform == "mw320" || chip_device_platform == "zephyr" || chip_device_platform == "beken" || chip_device_platform == "bl702" || chip_device_platform == "mt793x" || chip_device_platform == "SiWx917" || - chip_device_platform == "openiotsdk", + chip_device_platform == "openiotsdk" || chip_device_platform == "asr", "Please select a valid value for chip_device_platform") diff --git a/third_party/asr/asr582x/BUILD.gn b/third_party/asr/asr582x/BUILD.gn new file mode 100755 index 00000000000000..f6d8732420cb25 --- /dev/null +++ b/third_party/asr/asr582x/BUILD.gn @@ -0,0 +1,184 @@ +# Copyright (c) 2023 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/asr.gni") +import("${asr_sdk_build_root}/asr_sdk.gni") +import("${chip_root}/src/platform/ASR/args.gni") + +declare_args() { + # Build target to use for asr SDK. Use this to set global SDK defines. + asr_target_project = "" +} + +assert(asr_target_project != "", "asr_target_project must be specified") + +# Add includes, cflags, asmflags, etc in config +config("asr_sdk_config") { + _include_dirs = [ + "${asr_sdk_build_root}/asr_sdk/config", + "${asr_sdk_build_root}/asr_sdk/config/lwip_if", + "${asr_sdk_build_root}/asr_sdk/matter", + "${asr_sdk_build_root}/asr_sdk/freertos/Source/include", + "${asr_sdk_build_root}/asr_sdk/freertos/Source/portable/MemMang", + "${asr_sdk_build_root}/asr_sdk/freertos/Source/portable/GCC/ARM_CM4F", + "${asr_sdk_build_root}/asr_sdk/lib/wifi", + "${asr_sdk_build_root}/asr_sdk/lib/ble", + "${asr_sdk_build_root}/asr_sdk/lib/sys", + "${asr_sdk_build_root}/asr_sdk/lib/security", + "${asr_sdk_build_root}/asr_sdk/version", + "${asr_sdk_build_root}/asr_sdk/peripheral/duet/inc", + "${asr_sdk_build_root}/asr_sdk/common/duet", + "${asr_sdk_build_root}/asr_sdk/common/duet/easylogger", + "${asr_sdk_build_root}/asr_sdk/security/duet/inc", + "${asr_sdk_build_root}/asr_sdk/platform/duet", + "${asr_sdk_build_root}/asr_sdk/platform/duet/CMSIS/Include", + "${asr_sdk_build_root}/asr_sdk/platform/duet/system/include", + "${asr_sdk_build_root}/asr_sdk/platform/duet/kv/include", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/port/include", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include/lwip", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_app", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_app/lwip_app_ping", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include/lwip/prot", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include/netif", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_app/iperf", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_app/ota", + "${asr_sdk_build_root}/asr_sdk/lwip/mbedtls-mbedtls-2.18/include", + "${asr_sdk_build_root}/asr_sdk/lwip/mbedtls-mbedtls-2.18/include/mbedtls", + "${asr_sdk_build_root}/asr_sdk/lwip/mbedtls-mbedtls-2.18/asr_mbedtls/", + "${asr_sdk_build_root}/asr_sdk/lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt", + "${asr_sdk_build_root}/asr_sdk/demo/matter_demo/app/ble_demo/duet_hl_matter", + "${asr_sdk_build_root}/asr_sdk/platform/duet/kv/include", + ] + + # Also add project include path (passed in from project build) + proj_path = get_label_info(asr_target_project, "dir") + _include_dirs += [ "/" + rebase_path("${proj_path}/include", "/", ".") ] + + cflags = [] + foreach(include_dir, _include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] + } + + # Pull out defines from generated json + defines = [ + "_SPI_FLASH_240MHz_", + "DCDC_PFMMODE_CLOSE", + "LEGA_A0V2", + "DUET_CM4", + "_SPI_FLASH_ENABLE_", + "SYSTEM_SUPPORT_OS", + "WIFI_DEVICE", + "CFG_BATX=1", + "CFG_BARX=1", + "CFG_REORD_BUF=4", + "CFG_SPC=4", + "CFG_TXDESC0=4", + "CFG_TXDESC1=4", + "CFG_TXDESC2=4", + "CFG_TXDESC3=4", + "CFG_TXDESC4=4", + "CFG_CMON", + "CFG_MDM_VER_V21", + "CFG_SOFTAP_SUPPORT", + "CFG_SNIFFER_SUPPORT", + "CFG_CUS_FRAME", + "AT_USER_DEBUG", + "CFG_WF_DBG=1", + "__FPU_PRESENT=1", + "DX_CC_TEE", + "HASH_SHA_512_SUPPORTED", + "CC_HW_VERSION=0xF0", + "DLLI_MAX_BUFF_SIZE=0x10000", + "SSI_CONFIG_TRNG_MODE=0", + "LWIP_APP_IPERF", + "SYSTEM_RECOVERY", + "LWIP_DUALSTACK", + "SYSTEM_COREDUMP", + "CFG_REC", + "CFG_SNIFFER_UNICAST_SUPPORT", + "CFG_OS_VERSION_CHECK", + "PS_CLOSE_APLL", + "CFG_STA_AP_COEX_N", + "CFG_SOFTAP_SWITCH_CHAN_N", + "CFG_PLF_DUET", + "SONATA_RTOS_SUPPORT", + "CFG_SEG", + "CFG_DUET_FREERTOS", + "PRINTF2_SUPPORT", + "DUET_RF_SLEEP", + "CFG_DUET_BLE", + "CFG_RTC_INDEPENDENT", + "CFG_SAE", + "CFG_SAE_AUTH_OPT", + "CFG_MFP", + "CONFIG_IEEE80211W", + "WFA_CERTIFICATE_N", + "CFG_DUET_5822S", + "CFG_DUET_5822T", + "MBEDTLS_HW", + "MBEDTLS_HW_RSA", + "MBEDTLS_HW_ECC", + "MBEDTLS_HW_AES", + "MBEDTLS_HW_HASH", + "MBEDTLS_USER_CONFIG_FILE=", + "CONFIG_ENABLE_ASR_LEGA_RTOS=1", + "CFG_EASY_LOG_ENABLE=1", + "CFG_EASY_LOG_MODULE_EN=1", + ] + + cflags_c = [ + "-mcpu=cortex-m4", + "-Os", + "-mfloat-abi=softfp", + "-mfpu=fpv4-sp-d16", + "-mthumb", + "-ffunction-sections", + "-fdata-sections", + "-g", + "-Wall", + ] + + cflags_cc = cflags_c + + asmflags = cflags_c + + ldflags = cflags_c + + cflags_c += [ + "-Wno-sign-compare", + "-Wno-unused-function", + "-Wno-pointer-sign", + "-Wno-type-limits", + ] + + ldflags += [ "-Wl,--gc-sections" ] + + libs = [ + "${chip_root}/third_party/asr/${asr_ic_family}/asr_sdk/lib/5822s/libasr_combo_v6.a", + "${chip_root}/third_party/asr/${asr_ic_family}/asr_sdk/lib/ble/lib_ble_mesh.a", + "${chip_root}/third_party/asr/${asr_ic_family}/asr_sdk/lib/security/lib_security.a", + ] + + linker_script_flags = + "${asr_sdk_build_root}/asr_sdk/demo/matter_demo/app/ld/5822t/gcc.ld" + ldflags += [ "-T" + rebase_path(linker_script_flags, root_build_dir) ] + ble_symbol_flags = "${asr_sdk_build_root}/asr_sdk/lib/ble/asr_ble_rom_symbol_v20200507204845.txt" + ldflags += [ "-Wl,-R" + rebase_path(ble_symbol_flags, root_build_dir) ] +} + +group("asr_build") { + public_configs = [ ":asr_sdk_config" ] + public_deps = [ asr_target_project ] +} diff --git a/third_party/asr/asr582x/asr_sdk b/third_party/asr/asr582x/asr_sdk new file mode 160000 index 00000000000000..5773d8c2fa918d --- /dev/null +++ b/third_party/asr/asr582x/asr_sdk @@ -0,0 +1 @@ +Subproject commit 5773d8c2fa918d153d321a81fb237b8155384b75 diff --git a/third_party/asr/asr582x/asr_sdk.gni b/third_party/asr/asr582x/asr_sdk.gni new file mode 100755 index 00000000000000..18a04be42b60fa --- /dev/null +++ b/third_party/asr/asr582x/asr_sdk.gni @@ -0,0 +1,264 @@ +# Copyright (c) 2023 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/jlink.gni") +import("//build_overrides/mbedtls.gni") + +import("//build_overrides/asr.gni") + +# Defines an asr SDK build target. +# +# Parameters: +# sources - The sources files to build. +# +template("asr_sdk_sources") { + if (defined(invoker.asr_project_dir)) { + asr_project_dir = invoker.asr_project_dir + } + + # While most asr sdk includes come from the asr_sdk_config config (in + # BUILD.gn), this template gets instantiated by each project each of which + # provides a few extra includes/defines. Handle those here. + config("project_configs") { + include_dirs = [] + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + include_dirs += [ "${asr_project_dir}/include" ] + + defines = [] + if (defined(invoker.defines)) { + defines += invoker.defines + } + } + + sdk_target_name = target_name + + # Add sources here + source_set(sdk_target_name) { + sources = [] + if (defined(invoker.sources)) { + sources += invoker.sources + } + + _third_party_src = [ + #at + "at_cmd/atcmd_comm.c", + "at_cmd/atcmd_user.c", + "at_cmd/atcmd_matter.c", + + #peripheral + "peripheral/duet/src/duet_boot.c", + "peripheral/duet/src/duet_board.c", + "peripheral/duet/src/duet_efuse.c", + "peripheral/duet/src/duet_flash.c", + "peripheral/duet/src/duet_flash_alg.c", + "peripheral/duet/src/duet_wdg.c", + "peripheral/duet/src/duet_timer.c", + "peripheral/duet/src/duet_gpio.c", + "peripheral/duet/src/duet_i2c.c", + "peripheral/duet/src/duet_rf_spi.c", + "peripheral/duet/src/duet_pwm.c", + "peripheral/duet/src/duet_rtc.c", + "peripheral/duet/src/duet_pinmux.c", + "peripheral/duet/src/duet_uart.c", + "peripheral/duet/src/duet_adc.c", + "peripheral/duet/src/duet_dma.c", + + #platform + "platform/duet/system/sysCalls.c", + "platform/duet/system/soc_init.c", + "platform/duet/system/printf_uart.c", + "platform/duet/system/printf-stdarg.c", + "platform/duet/system/system_cm4.c", + "platform/duet/system/startup_cm4.S", + "platform/duet/ethernetif_wifi.c", + + #rtos + "platform/duet/lega_rtos.c", + "freertos/Source/croutine.c", + "freertos/Source/event_groups.c", + "freertos/Source/list.c", + "freertos/Source/queue.c", + "freertos/Source/tasks.c", + "freertos/Source/timers.c", + "freertos/Source/portable/MemMang/heap_5.c", + "freertos/Source/portable/GCC/ARM_CM4F/port.c", + + #ble + "demo/matter_demo/app/ble_demo/duet_hl_matter/app.c", + "demo/matter_demo/app/ble_demo/duet_hl_matter/user_platform.c", + + #matter + "matter/asr_factory_config.c", + + #elog + "common/duet/easylogger/elog_async.c", + "common/duet/easylogger/elog_buf.c", + "common/duet/easylogger/elog_module.c", + "common/duet/easylogger/elog_port.c", + "common/duet/easylogger/elog_utils.c", + "common/duet/easylogger/elog.c", + + #lwip + "lwip/lwip_2.1.2/netif/ethernet.c", + "lwip/lwip_2.1.2/port/sys_arch.c", + "lwip/lwip_2.1.2/api/api_lib.c", + "lwip/lwip_2.1.2/api/api_msg.c", + "lwip/lwip_2.1.2/api/err.c", + "lwip/lwip_2.1.2/api/if_api.c", + "lwip/lwip_2.1.2/api/netbuf.c", + "lwip/lwip_2.1.2/api/netdb.c", + "lwip/lwip_2.1.2/api/netifapi.c", + "lwip/lwip_2.1.2/api/sockets.c", + "lwip/lwip_2.1.2/api/tcpip.c", + "lwip/lwip_2.1.2/core/altcp.c", + "lwip/lwip_2.1.2/core/altcp_alloc.c", + "lwip/lwip_2.1.2/core/altcp_tcp.c", + "lwip/lwip_2.1.2/core/def.c", + "lwip/lwip_2.1.2/core/dns.c", + "lwip/lwip_2.1.2/core/inet_chksum.c", + "lwip/lwip_2.1.2/core/init.c", + "lwip/lwip_2.1.2/core/ip.c", + "lwip/lwip_2.1.2/core/ipv4/autoip.c", + "lwip/lwip_2.1.2/core/ipv4/dhcp.c", + "lwip/lwip_2.1.2/core/ipv4/etharp.c", + "lwip/lwip_2.1.2/core/ipv4/icmp.c", + "lwip/lwip_2.1.2/core/ipv4/igmp.c", + "lwip/lwip_2.1.2/core/ipv4/ip4.c", + "lwip/lwip_2.1.2/core/ipv4/ip4_addr.c", + "lwip/lwip_2.1.2/core/ipv4/ip4_frag.c", + "lwip/lwip_2.1.2/core/ipv6/dhcp6.c", + "lwip/lwip_2.1.2/core/ipv6/ethip6.c", + "lwip/lwip_2.1.2/core/ipv6/icmp6.c", + "lwip/lwip_2.1.2/core/ipv6/inet6.c", + "lwip/lwip_2.1.2/core/ipv6/ip6.c", + "lwip/lwip_2.1.2/core/ipv6/ip6_addr.c", + "lwip/lwip_2.1.2/core/ipv6/ip6_frag.c", + "lwip/lwip_2.1.2/core/ipv6/mld6.c", + "lwip/lwip_2.1.2/core/ipv6/nd6.c", + "lwip/lwip_2.1.2/core/lwip_hooks.c", + "lwip/lwip_2.1.2/core/mem.c", + "lwip/lwip_2.1.2/core/memp.c", + "lwip/lwip_2.1.2/core/netif.c", + "lwip/lwip_2.1.2/core/pbuf.c", + "lwip/lwip_2.1.2/core/raw.c", + "lwip/lwip_2.1.2/core/stats.c", + "lwip/lwip_2.1.2/core/sys.c", + "lwip/lwip_2.1.2/core/tcp.c", + "lwip/lwip_2.1.2/core/tcp_in.c", + "lwip/lwip_2.1.2/core/tcp_out.c", + "lwip/lwip_2.1.2/core/timeouts.c", + "lwip/lwip_2.1.2/core/udp.c", + + #mbedtls + "lwip/mbedtls-mbedtls-2.18/library/aes.c", + "lwip/mbedtls-mbedtls-2.18/library/aesni.c", + "lwip/mbedtls-mbedtls-2.18/library/arc4.c", + "lwip/mbedtls-mbedtls-2.18/library/aria.c", + "lwip/mbedtls-mbedtls-2.18/library/asn1parse.c", + "lwip/mbedtls-mbedtls-2.18/library/asn1write.c", + "lwip/mbedtls-mbedtls-2.18/library/base64.c", + "lwip/mbedtls-mbedtls-2.18/library/bignum.c", + "lwip/mbedtls-mbedtls-2.18/library/blowfish.c", + "lwip/mbedtls-mbedtls-2.18/library/camellia.c", + "lwip/mbedtls-mbedtls-2.18/library/ccm.c", + "lwip/mbedtls-mbedtls-2.18/library/certs.c", + "lwip/mbedtls-mbedtls-2.18/library/chacha20.c", + "lwip/mbedtls-mbedtls-2.18/library/chachapoly.c", + "lwip/mbedtls-mbedtls-2.18/library/cipher.c", + "lwip/mbedtls-mbedtls-2.18/library/cipher_wrap.c", + "lwip/mbedtls-mbedtls-2.18/library/cmac.c", + "lwip/mbedtls-mbedtls-2.18/library/ctr_drbg.c", + "lwip/mbedtls-mbedtls-2.18/library/debug.c", + "lwip/mbedtls-mbedtls-2.18/library/des.c", + "lwip/mbedtls-mbedtls-2.18/library/dhm.c", + "lwip/mbedtls-mbedtls-2.18/library/ecdh.c", + "lwip/mbedtls-mbedtls-2.18/library/ecdsa.c", + "lwip/mbedtls-mbedtls-2.18/library/ecjpake.c", + "lwip/mbedtls-mbedtls-2.18/library/ecp.c", + "lwip/mbedtls-mbedtls-2.18/library/ecp_curves.c", + "lwip/mbedtls-mbedtls-2.18/library/entropy.c", + "lwip/mbedtls-mbedtls-2.18/library/entropy_poll.c", + "lwip/mbedtls-mbedtls-2.18/library/error.c", + "lwip/mbedtls-mbedtls-2.18/library/gcm.c", + "lwip/mbedtls-mbedtls-2.18/library/havege.c", + "lwip/mbedtls-mbedtls-2.18/library/hkdf.c", + "lwip/mbedtls-mbedtls-2.18/library/hmac_drbg.c", + "lwip/mbedtls-mbedtls-2.18/library/md.c", + "lwip/mbedtls-mbedtls-2.18/library/md2.c", + "lwip/mbedtls-mbedtls-2.18/library/md4.c", + "lwip/mbedtls-mbedtls-2.18/library/md5.c", + "lwip/mbedtls-mbedtls-2.18/library/md_wrap.c", + "lwip/mbedtls-mbedtls-2.18/library/memory_buffer_alloc.c", + "lwip/mbedtls-mbedtls-2.18/library/nist_kw.c", + "lwip/mbedtls-mbedtls-2.18/library/oid.c", + "lwip/mbedtls-mbedtls-2.18/library/padlock.c", + "lwip/mbedtls-mbedtls-2.18/library/pem.c", + "lwip/mbedtls-mbedtls-2.18/library/pk.c", + "lwip/mbedtls-mbedtls-2.18/library/pk_wrap.c", + "lwip/mbedtls-mbedtls-2.18/library/pkcs11.c", + "lwip/mbedtls-mbedtls-2.18/library/pkcs12.c", + "lwip/mbedtls-mbedtls-2.18/library/pkcs5.c", + "lwip/mbedtls-mbedtls-2.18/library/pkparse.c", + "lwip/mbedtls-mbedtls-2.18/library/pkwrite.c", + "lwip/mbedtls-mbedtls-2.18/library/platform.c", + "lwip/mbedtls-mbedtls-2.18/library/platform_util.c", + "lwip/mbedtls-mbedtls-2.18/library/poly1305.c", + "lwip/mbedtls-mbedtls-2.18/library/ripemd160.c", + "lwip/mbedtls-mbedtls-2.18/library/rsa.c", + "lwip/mbedtls-mbedtls-2.18/library/rsa_internal.c", + "lwip/mbedtls-mbedtls-2.18/library/sha1.c", + "lwip/mbedtls-mbedtls-2.18/library/sha256.c", + "lwip/mbedtls-mbedtls-2.18/library/sha512.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_cache.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_ciphersuites.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_cli.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_cookie.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_srv.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_ticket.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_tls.c", + "lwip/mbedtls-mbedtls-2.18/library/threading.c", + "lwip/mbedtls-mbedtls-2.18/library/timing.c", + "lwip/mbedtls-mbedtls-2.18/library/version.c", + "lwip/mbedtls-mbedtls-2.18/library/version_features.c", + "lwip/mbedtls-mbedtls-2.18/library/x509.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_create.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_crl.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_crt.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_csr.c", + "lwip/mbedtls-mbedtls-2.18/library/x509write_crt.c", + "lwip/mbedtls-mbedtls-2.18/library/x509write_csr.c", + "lwip/mbedtls-mbedtls-2.18/library/xtea.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/entropy_hardware_alt.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/aes_alt.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/sha1_alt.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/sha256_alt.c", + ] + + foreach(src, _third_party_src) { + sources += [ rebase_path(src, + "${asr_project_dir}", + "${asr_sdk_build_root}/asr_sdk/") ] + } + + public_deps = [ "${chip_root}/src/lwip:lwip" ] + + public_configs = [ ":project_configs" ] + if (defined(invoker.public_configs)) { + public_configs += invoker.public_configs + } + } +} diff --git a/third_party/asr/asr595x/BUILD.gn b/third_party/asr/asr595x/BUILD.gn new file mode 100755 index 00000000000000..c4f40e04acc066 --- /dev/null +++ b/third_party/asr/asr595x/BUILD.gn @@ -0,0 +1,203 @@ +# Copyright (c) 2023 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/asr.gni") +import("${asr_sdk_build_root}/asr_sdk.gni") +import("${chip_root}/src/platform/ASR/args.gni") + +declare_args() { + # Build target to use for asr SDK. Use this to set global SDK defines. + asr_target_project = "" +} + +assert(asr_target_project != "", "asr_target_project must be specified") + +# Add includes, cflags, asmflags, etc in config +config("asr_sdk_config") { + _include_dirs = [ + "${asr_sdk_build_root}/asr_sdk/config", + "${asr_sdk_build_root}/asr_sdk/config/lwip_if", + "${asr_sdk_build_root}/asr_sdk/matter", + "${asr_sdk_build_root}/asr_sdk/at_cmd", + "${asr_sdk_build_root}/asr_sdk/common/alto/inc", + "${asr_sdk_build_root}/asr_sdk/common/alto/easylogger", + "${asr_sdk_build_root}/asr_sdk/freertos", + "${asr_sdk_build_root}/asr_sdk/freertos/Source/include", + "${asr_sdk_build_root}/asr_sdk/freertos/Source/portable/GCC", + "${asr_sdk_build_root}/asr_sdk/legartos", + "${asr_sdk_build_root}/asr_sdk/lib/ble", + "${asr_sdk_build_root}/asr_sdk/lib/security", + "${asr_sdk_build_root}/asr_sdk/lib/sys", + "${asr_sdk_build_root}/asr_sdk/lib/wifi", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include/lwip", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include/lwip/prot", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/include/netif", + "${asr_sdk_build_root}/asr_sdk/lwip/lwip_2.1.2/port/include", + "${asr_sdk_build_root}/asr_sdk/lwip/mbedtls-mbedtls-2.18/include", + "${asr_sdk_build_root}/asr_sdk/lwip/mbedtls-mbedtls-2.18/asr_mbedtls", + "${asr_sdk_build_root}/asr_sdk/lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt", + "${asr_sdk_build_root}/asr_sdk/peripheral/asr/inc", + "${asr_sdk_build_root}/asr_sdk/peripheral/asr/inc/alto", + "${asr_sdk_build_root}/asr_sdk/peripheral/asr/inc/alto/alto", + "${asr_sdk_build_root}/asr_sdk/platform/alto/NMSIS/Core/Include", + "${asr_sdk_build_root}/asr_sdk/platform/alto/common", + "${asr_sdk_build_root}/asr_sdk/platform/alto/kv/include", + "${asr_sdk_build_root}/asr_sdk/platform/alto/system/include", + "${asr_sdk_build_root}/asr_sdk/projects/alto_demo/ble_demo/duet_hl_matter", + "${asr_sdk_build_root}/asr_sdk/version", + ] + + # Also add project include path (passed in from project build) + proj_path = get_label_info(asr_target_project, "dir") + _include_dirs += [ "/" + rebase_path("${proj_path}/include", "/", ".") ] + + cflags = [] + foreach(include_dir, _include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] + } + + # Pull out defines from generated json + defines = [ + "ALTO_BLE_NO_BLOCK", + "__VTOR_PRESENT=1", + "CFG_DUET_BLE", + "CFG_REL", + "SONATA_RTOS_SUPPORT", + "CODE_USE_ALTO", + "_SPI_FLASH_240MHz_", + "DCDC_PFMMODE_CLOSE", + "LEGA_A0V2", + "_SPI_FLASH_ENABLE_", + "SYSTEM_SUPPORT_OS", + "WIFI_DEVICE", + "CFG_BATX=1", + "CFG_BARX=2", + "CFG_REORD_BUF=4", + "CFG_SPC=4", + "CFG_TXDESC0=4", + "CFG_TXDESC1=4", + "CFG_TXDESC2=4", + "CFG_TXDESC3=4", + "CFG_TXDESC4=4", + "CFG_CMON", + "CFG_MDM_VER_V30", + "CFG_HE", + "CFG_SOFTAP_SUPPORT", + "CFG_SNIFFER_SUPPORT", + "CFG_CUS_FRAME", + "CFG_WF_DBG=1", + "__FPU_PRESENT=1", + "DX_CC_TEE", + "HASH_SHA_512_SUPPORTED", + "CC_HW_VERSION=0xF0", + "DLLI_MAX_BUFF_SIZE=0x10000", + "SSI_CONFIG_TRNG_MODE=0", + "LWIP_APP_IPERF", + "SYSTEM_RECOVERY", + "SYSTEM_COREDUMP", + "CFG_REC", + "CFG_SNIFFER_UNICAST_SUPPORT", + "PS_CLOSE_APLL", + "CFG_SEG", + "PRINTF2_SUPPORT", + "AT_USER_DEBUG", + "CFG_PLF_RV32", + "SECURITY_ENGINE_INIT", + "DUET_RF_SLEEP", + "LOW_LEVEL_FLASH_RW_SUPPORT", + "CFG_RTC_INDEPENDENT", + "DHCPS_POOL_SET_SUPPORT", + "CFG_OPTIMIZE_CHANNEL_SENSITIVITY", + "CFG_SAE", + "USE_SMALL_STACK", + "CFG_MFP", + "CONFIG_IEEE80211W", + "WFA_CERTIFICATE_N", + "PRINTF2_SUPPORT", + "CFG_PLF_RV32", + "LEGA_A0V2", + "RTOS_FREERTOS", + "LEGA_RTOS_SUPPORT", + "LWIP_APP_IPERF", + "AT_USER_DEBUG", + "KV_SUPPORT", + "LWIP_DUALSTACK", + "DEBUG_BACKTRACE", + "DOWNLOAD_MODE=0", + "MULTI_HEAP_REGIONS", + "MBEDTLS_HW", + "MBEDTLS_HW_RSA", + "MBEDTLS_HW_ECC", + "MBEDTLS_HW_AES", + "MBEDTLS_HW_HASH", + "MBEDTLS_USER_CONFIG_FILE=", + "CFG_FLASH_MAX_SIZE=0x400000", + "CONFIG_ENABLE_ASR_LEGA_RTOS=1", + "CFG_EASY_LOG_ENABLE=1", + "CFG_EASY_LOG_MODULE_EN=1", + ] + + cflags_c = [ + "-march=rv32imafc", + "-mabi=ilp32f", + "-mcmodel=medany", + "-Os", + "-fno-omit-frame-pointer", + "-fshort-enums", + "-fno-common", + "-ffunction-sections", + "-fdata-sections", + "-g", + "-Wall", + ] + + cflags_cc = cflags_c + + asmflags = cflags_c + + cflags_c += [ + "-Wno-sign-compare", + "-Wno-unused-function", + "-Wno-pointer-sign", + "-Wno-type-limits", + ] + + ldflags = [ + "-march=rv32imafc", + "-mabi=ilp32f", + "-mcmodel=medany", + "-lm", + "-g", + "-Wall", + "-lstdc++", + "-nostartfiles", + "-Wl,--gc-sections", + ] + + libs = [ "${chip_root}/third_party/asr/${asr_ic_family}/asr_sdk/lib/libasr_wifi6_v6.a" ] + + linker_script_flags = + "${asr_sdk_build_root}/asr_sdk/platform/alto/linker/gcc_flashxip.ld" + ldflags += [ "-T" + rebase_path(linker_script_flags, root_build_dir) ] + ble_symbol_flags = + "${asr_sdk_build_root}/asr_sdk/lib/ble/ble_rom_v10_0_8_asr_symbol.txt" + ldflags += [ "-Wl,-R" + rebase_path(ble_symbol_flags, root_build_dir) ] + ldflags += [ "-Wl,-z,max-page-size=4096" ] +} + +group("asr_build") { + public_configs = [ ":asr_sdk_config" ] + public_deps = [ asr_target_project ] +} diff --git a/third_party/asr/asr595x/asr_sdk b/third_party/asr/asr595x/asr_sdk new file mode 160000 index 00000000000000..3db19fcb8cfcd5 --- /dev/null +++ b/third_party/asr/asr595x/asr_sdk @@ -0,0 +1 @@ +Subproject commit 3db19fcb8cfcd596c48b44df229e60a1bed30e8a diff --git a/third_party/asr/asr595x/asr_sdk.gni b/third_party/asr/asr595x/asr_sdk.gni new file mode 100755 index 00000000000000..6c30da58d7c032 --- /dev/null +++ b/third_party/asr/asr595x/asr_sdk.gni @@ -0,0 +1,278 @@ +# Copyright (c) 2023 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/jlink.gni") +import("//build_overrides/mbedtls.gni") + +import("//build_overrides/asr.gni") + +# Defines an asr SDK build target. +# +# Parameters: +# sources - The sources files to build. +# +template("asr_sdk_sources") { + if (defined(invoker.asr_project_dir)) { + asr_project_dir = invoker.asr_project_dir + } + + # While most asr sdk includes come from the asr_sdk_config config (in + # BUILD.gn), this template gets instantiated by each project each of which + # provides a few extra includes/defines. Handle those here. + config("project_configs") { + include_dirs = [] + if (defined(invoker.include_dirs)) { + include_dirs += invoker.include_dirs + } + include_dirs += [ "${asr_project_dir}/include" ] + + defines = [] + if (defined(invoker.defines)) { + defines += invoker.defines + } + } + + sdk_target_name = target_name + + # Add sources here + source_set(sdk_target_name) { + sources = [] + if (defined(invoker.sources)) { + sources += invoker.sources + } + + _third_party_src = [ + #at + "at_cmd/atcmd_comm.c", + "at_cmd/atcmd_user.c", + "at_cmd/atcmd_matter.c", + + #common + "common/alto/src/alto_common.c", + "common/alto/src/hbird_common.c", + "common/alto/src/system_hbird.c", + "common/alto/src/GCC/startup_hbird.S", + "common/alto/src/GCC/intexc_hbird.S", + + #rtos + "freertos/Source/croutine.c", + "freertos/Source/event_groups.c", + "freertos/Source/list.c", + "freertos/Source/portable/GCC/port.c", + "freertos/Source/portable/GCC/portasm.S", + "freertos/Source/portable/MemMang/heap_5.c", + "freertos/Source/queue.c", + "freertos/Source/stream_buffer.c", + "freertos/Source/tasks.c", + "freertos/Source/timers.c", + "legartos/lega_rtos.c", + + #peripheral + "peripheral/asr/src/alto/asr_alto_apll_rf.c", + "peripheral/asr/src/alto/asr_alto_board.c", + "peripheral/asr/src/alto/asr_alto_efuse.c", + "peripheral/asr/src/alto/asr_alto_pinmux.c", + "peripheral/asr/src/alto/asr_alto_port.c", + "peripheral/asr/src/alto/asr_alto_boot.c", + "peripheral/asr/src/alto/asr_alto_ram_layout.c", + "peripheral/asr/src/asr_dma.c", + "peripheral/asr/src/asr_efuse.c", + "peripheral/asr/src/asr_flash.c", + "peripheral/asr/src/asr_flash_alg.c", + "peripheral/asr/src/asr_i2c.c", + "peripheral/asr/src/asr_gpio.c", + "peripheral/asr/src/asr_pwm.c", + "peripheral/asr/src/asr_pinmux.c", + "peripheral/asr/src/asr_adc.c", + "peripheral/asr/src/asr_psram.c", + "peripheral/asr/src/asr_rf_spi.c", + "peripheral/asr/src/asr_rtc.c", + "peripheral/asr/src/asr_timer.c", + "peripheral/asr/src/asr_uart.c", + "peripheral/asr/src/asr_wdg.c", + + #platform + "platform/alto/system/prinfs/printf-stdarg.c", + "platform/alto/system/prinfs/printf_uart.c", + "platform/alto/system/prinfs/sysCalls.c", + "platform/alto/system/soc/soc_init.c", + "platform/alto/system/soc/system_cm4.c", + "platform/alto/system/soc/systick_delay.c", + + #elog + "common/alto/easylogger/elog_async.c", + "common/alto/easylogger/elog_buf.c", + "common/alto/easylogger/elog_module.c", + "common/alto/easylogger/elog_port.c", + "common/alto/easylogger/elog_utils.c", + "common/alto/easylogger/elog.c", + + #ble + "projects/alto_demo/ble_demo/duet_hl_matter/app.c", + "projects/alto_demo/ble_demo/duet_hl_matter/user_platform.c", + + #matter + "matter/asr_factory_config.c", + + #lwip + "lwip/lwip_2.1.2/netif/ethernet.c", + "lwip/lwip_2.1.2/port/sys_arch.c", + "lwip/lwip_2.1.2/api/api_lib.c", + "lwip/lwip_2.1.2/api/api_msg.c", + "lwip/lwip_2.1.2/api/err.c", + "lwip/lwip_2.1.2/api/if_api.c", + "lwip/lwip_2.1.2/api/netbuf.c", + "lwip/lwip_2.1.2/api/netdb.c", + "lwip/lwip_2.1.2/api/netifapi.c", + "lwip/lwip_2.1.2/api/sockets.c", + "lwip/lwip_2.1.2/api/tcpip.c", + "lwip/lwip_2.1.2/core/altcp.c", + "lwip/lwip_2.1.2/core/altcp_alloc.c", + "lwip/lwip_2.1.2/core/altcp_tcp.c", + "lwip/lwip_2.1.2/core/def.c", + "lwip/lwip_2.1.2/core/dns.c", + "lwip/lwip_2.1.2/core/inet_chksum.c", + "lwip/lwip_2.1.2/core/init.c", + "lwip/lwip_2.1.2/core/ip.c", + "lwip/lwip_2.1.2/core/ipv4/autoip.c", + "lwip/lwip_2.1.2/core/ipv4/dhcp.c", + "lwip/lwip_2.1.2/core/ipv4/etharp.c", + "lwip/lwip_2.1.2/core/ipv4/icmp.c", + "lwip/lwip_2.1.2/core/ipv4/igmp.c", + "lwip/lwip_2.1.2/core/ipv4/ip4.c", + "lwip/lwip_2.1.2/core/ipv4/ip4_addr.c", + "lwip/lwip_2.1.2/core/ipv4/ip4_frag.c", + "lwip/lwip_2.1.2/core/ipv6/dhcp6.c", + "lwip/lwip_2.1.2/core/ipv6/ethip6.c", + "lwip/lwip_2.1.2/core/ipv6/icmp6.c", + "lwip/lwip_2.1.2/core/ipv6/inet6.c", + "lwip/lwip_2.1.2/core/ipv6/ip6.c", + "lwip/lwip_2.1.2/core/ipv6/ip6_addr.c", + "lwip/lwip_2.1.2/core/ipv6/ip6_frag.c", + "lwip/lwip_2.1.2/core/ipv6/mld6.c", + "lwip/lwip_2.1.2/core/ipv6/nd6.c", + "lwip/lwip_2.1.2/core/lwip_hooks.c", + "lwip/lwip_2.1.2/core/mem.c", + "lwip/lwip_2.1.2/core/memp.c", + "lwip/lwip_2.1.2/core/netif.c", + "lwip/lwip_2.1.2/core/pbuf.c", + "lwip/lwip_2.1.2/core/raw.c", + "lwip/lwip_2.1.2/core/stats.c", + "lwip/lwip_2.1.2/core/sys.c", + "lwip/lwip_2.1.2/core/tcp.c", + "lwip/lwip_2.1.2/core/tcp_in.c", + "lwip/lwip_2.1.2/core/tcp_out.c", + "lwip/lwip_2.1.2/core/timeouts.c", + "lwip/lwip_2.1.2/core/udp.c", + + #mbedtls + "lwip/mbedtls-mbedtls-2.18/library/aes.c", + "lwip/mbedtls-mbedtls-2.18/library/aesni.c", + "lwip/mbedtls-mbedtls-2.18/library/arc4.c", + "lwip/mbedtls-mbedtls-2.18/library/aria.c", + "lwip/mbedtls-mbedtls-2.18/library/asn1parse.c", + "lwip/mbedtls-mbedtls-2.18/library/asn1write.c", + "lwip/mbedtls-mbedtls-2.18/library/base64.c", + "lwip/mbedtls-mbedtls-2.18/library/bignum.c", + "lwip/mbedtls-mbedtls-2.18/library/blowfish.c", + "lwip/mbedtls-mbedtls-2.18/library/camellia.c", + "lwip/mbedtls-mbedtls-2.18/library/ccm.c", + "lwip/mbedtls-mbedtls-2.18/library/certs.c", + "lwip/mbedtls-mbedtls-2.18/library/chacha20.c", + "lwip/mbedtls-mbedtls-2.18/library/chachapoly.c", + "lwip/mbedtls-mbedtls-2.18/library/cipher.c", + "lwip/mbedtls-mbedtls-2.18/library/cipher_wrap.c", + "lwip/mbedtls-mbedtls-2.18/library/cmac.c", + "lwip/mbedtls-mbedtls-2.18/library/ctr_drbg.c", + "lwip/mbedtls-mbedtls-2.18/library/debug.c", + "lwip/mbedtls-mbedtls-2.18/library/des.c", + "lwip/mbedtls-mbedtls-2.18/library/dhm.c", + "lwip/mbedtls-mbedtls-2.18/library/ecdh.c", + "lwip/mbedtls-mbedtls-2.18/library/ecdsa.c", + "lwip/mbedtls-mbedtls-2.18/library/ecjpake.c", + "lwip/mbedtls-mbedtls-2.18/library/ecp.c", + "lwip/mbedtls-mbedtls-2.18/library/ecp_curves.c", + "lwip/mbedtls-mbedtls-2.18/library/entropy.c", + "lwip/mbedtls-mbedtls-2.18/library/entropy_poll.c", + "lwip/mbedtls-mbedtls-2.18/library/error.c", + "lwip/mbedtls-mbedtls-2.18/library/gcm.c", + "lwip/mbedtls-mbedtls-2.18/library/havege.c", + "lwip/mbedtls-mbedtls-2.18/library/hkdf.c", + "lwip/mbedtls-mbedtls-2.18/library/hmac_drbg.c", + "lwip/mbedtls-mbedtls-2.18/library/md.c", + "lwip/mbedtls-mbedtls-2.18/library/md2.c", + "lwip/mbedtls-mbedtls-2.18/library/md4.c", + "lwip/mbedtls-mbedtls-2.18/library/md5.c", + "lwip/mbedtls-mbedtls-2.18/library/md_wrap.c", + "lwip/mbedtls-mbedtls-2.18/library/memory_buffer_alloc.c", + "lwip/mbedtls-mbedtls-2.18/library/nist_kw.c", + "lwip/mbedtls-mbedtls-2.18/library/oid.c", + "lwip/mbedtls-mbedtls-2.18/library/padlock.c", + "lwip/mbedtls-mbedtls-2.18/library/pem.c", + "lwip/mbedtls-mbedtls-2.18/library/pk.c", + "lwip/mbedtls-mbedtls-2.18/library/pk_wrap.c", + "lwip/mbedtls-mbedtls-2.18/library/pkcs11.c", + "lwip/mbedtls-mbedtls-2.18/library/pkcs12.c", + "lwip/mbedtls-mbedtls-2.18/library/pkcs5.c", + "lwip/mbedtls-mbedtls-2.18/library/pkparse.c", + "lwip/mbedtls-mbedtls-2.18/library/pkwrite.c", + "lwip/mbedtls-mbedtls-2.18/library/platform.c", + "lwip/mbedtls-mbedtls-2.18/library/platform_util.c", + "lwip/mbedtls-mbedtls-2.18/library/poly1305.c", + "lwip/mbedtls-mbedtls-2.18/library/ripemd160.c", + "lwip/mbedtls-mbedtls-2.18/library/rsa.c", + "lwip/mbedtls-mbedtls-2.18/library/rsa_internal.c", + "lwip/mbedtls-mbedtls-2.18/library/sha1.c", + "lwip/mbedtls-mbedtls-2.18/library/sha256.c", + "lwip/mbedtls-mbedtls-2.18/library/sha512.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_cache.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_ciphersuites.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_cli.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_cookie.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_srv.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_ticket.c", + "lwip/mbedtls-mbedtls-2.18/library/ssl_tls.c", + "lwip/mbedtls-mbedtls-2.18/library/threading.c", + "lwip/mbedtls-mbedtls-2.18/library/timing.c", + "lwip/mbedtls-mbedtls-2.18/library/version.c", + "lwip/mbedtls-mbedtls-2.18/library/version_features.c", + "lwip/mbedtls-mbedtls-2.18/library/x509.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_create.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_crl.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_crt.c", + "lwip/mbedtls-mbedtls-2.18/library/x509_csr.c", + "lwip/mbedtls-mbedtls-2.18/library/x509write_crt.c", + "lwip/mbedtls-mbedtls-2.18/library/x509write_csr.c", + "lwip/mbedtls-mbedtls-2.18/library/xtea.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/entropy_hardware_alt.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/aes_alt.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/sha1_alt.c", + "lwip/mbedtls-mbedtls-2.18/asr_mbedtls/alt/sha256_alt.c", + ] + + foreach(src, _third_party_src) { + sources += [ rebase_path(src, + "${asr_project_dir}", + "${asr_sdk_build_root}/asr_sdk/") ] + } + + public_deps = [ "${chip_root}/src/lwip:lwip" ] + + public_configs = [ ":project_configs" ] + if (defined(invoker.public_configs)) { + public_configs += invoker.public_configs + } + } +} diff --git a/third_party/asr/asr_arm.gni b/third_party/asr/asr_arm.gni new file mode 100644 index 00000000000000..18d8d197ddc3d3 --- /dev/null +++ b/third_party/asr/asr_arm.gni @@ -0,0 +1,19 @@ +# Copyright (c) 2023 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. + +arm_arch = "armv7e-m" +arm_abi = "aapcs" +arm_cpu = "cortex-m4" +arm_float_abi = "softfp" +arm_fpu = "fpv4-sp-d16" diff --git a/third_party/asr/asr_executable.gni b/third_party/asr/asr_executable.gni new file mode 100644 index 00000000000000..8347b02ef77265 --- /dev/null +++ b/third_party/asr/asr_executable.gni @@ -0,0 +1,42 @@ +# Copyright (c) 2023 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/asr.gni") +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") +import("${build_root}/toolchain/flashable_executable.gni") + +template("asr_executable") { + output_base_name = get_path_info(invoker.output_name, "name") + + objcopy_image_name = output_base_name + ".bin" + objcopy_image_format = "binary" + + if (asr_ic_family == "asr595x") { + objcopy = "${asr_toolchain_root}riscv-asr-elf-objcopy" + } else if (asr_ic_family == "asr582x") { + objcopy = "${asr_toolchain_root}arm-none-eabi-objcopy" + } else { + objcopy = "objcopy" + } + + #Copy flashing dependencies to the output directory so that the output + #is collectively self-contained; this allows flashing to work reliably + #even if the build and flashing steps take place on different machines + #or in different containers. + + flashable_executable(target_name) { + forward_variables_from(invoker, "*") + } +} diff --git a/third_party/asr/asr_riscv.gni b/third_party/asr/asr_riscv.gni new file mode 100644 index 00000000000000..227bcdb6664b0f --- /dev/null +++ b/third_party/asr/asr_riscv.gni @@ -0,0 +1,16 @@ +# Copyright (c) 2023 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. + +riscv_arch = "rv32imafc" +riscv_abi = "ilp32f"